leetcode刷题笔记——广度优先搜索
目前完成的广度优先搜索相关的leetcode算法题序号:
简单:257
中等:200, 1631
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-itinerary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
文章目录
算法理解
广度优先搜索在解题时,是针对搜索类问题与深度优先搜索相对的两种解题思路。
究竟是每次针对一种情况先一条道走到黑,如果不行换另一条路(深度优先),还是在每一步上都考虑所有的可能性,同步的去寻找所有的可能结果(广度优先)。针对不同的问题,这两种思路都有自己的优越性,具体如何选择自己慢慢体会吧。
初次遇到广度优先搜索,是在迷宫问题上,和深度优先搜索作为迷宫问题的两种解法思路碰到的。迷宫问题可以简单描述为:针对一个0-1矩阵表示的迷宫,给定起点和终点,寻找一条由起点到终点的路径。
正如深度优先搜索刷题笔记中提到的,这个题用深度优先搜索实现起来更直观简单一些。广度优先搜索虽然在理论上理解起来也没有太大的障碍,但是在实现的过程中,使用队列的时候,对于算法新手的我来说,由于不是很熟悉队列数据结构的使用,对于进队出队,出队后元素如何存储在路径记录表中的顺序关系不太熟悉,而且到达终点之后如何在路径记录表中按照记录的索引值找到对应的完整路径也造成一定的麻烦,所以在运用广度优先搜索算法的时候,确实会有一定的麻烦。
不过广度优先搜索算法在寻找路径的过程中,不需要在遇到死胡同之后频繁的进行“回溯”操作,所以在时间复杂度上一般要低一些(对应的空间复杂度一般要比广度优先搜索要高一点),而且广度优先搜索算法能够保证找到的一定是最短路径中的一种情况。
提示:以下是深度优先搜索的刷题笔记
一、257题:二叉树的所有路径
二叉树是指每个节点至多有2个分支的树结构,包括满二叉树和完全二叉树等特殊结构,本题的对象是普通二叉树。
1.题干
给定一个二叉树,返回所有从根节点到叶子节点的路径。
给定的树结构是带有左右子节点的数据节点,原始数据为根节点。
2.思路
广度优先搜索基于队列(先进先出)的机制,利用广度优先搜索算法进行解题时,基本的思路就是在每一步考问题的所有可能性,将所有可能性添加到队列中,然后按照队列的顺序依次对所有可能性同步逐个进行处理。
在这个题目中,初始节点即为根节点,从根节点开始迭代,每一步考虑的可能性就是是否有左右子节点,如果有左右子节点,就更新各种可能性下的路径,并将各种可能性更新到队列中,如果达到终止条件:搜索到达叶子节点(无左右子节点),则将路径输出。
3.代码
class Solution:
def binaryTreePaths(self, root: TreeNode) -> List[str]:
paths = []
if not root:#如果根节点为空,则没有节点,也就不存在路径
return paths
node_queue = collections.deque([root])#建立节点的队列,用于存储二叉树分支搜索每一步的可能性
path_queue = collections.deque([str(root.val)])#路径队列,用于存储与节点队列对应的各种路径,记录顺序必须一致
while len(node_queue) > 0:#节点队列不为空,就一直循环
node = node_queue.popleft()#导出节点队列中最前面的一个节点,按顺序逐一处理
path = path_queue.popleft()#导出与节点对应的路径
if not node.left and not node.right:#如果队列最前方的节点是叶子节点,则将路径存储到结果列表中,这个叶子节点已经出队,不会在后续重复考虑
paths.append(path)
if node.left:#如果当前节点有左右子节点,则将左右子节点添加到节点队列中,并更新各个子节点对应的路径,加入到路径对应中,保证了节点队列与路径队列的顺序一一对应