BFS总结
Posted pdev
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BFS总结相关的知识,希望对你有一定的参考价值。
能够用 BFS 解决的问题,一定不要用 DFS 去做! 因为用 Recursion 实现的 DFS 可能造成 StackOverflow! (NonRecursion 的 DFS 一来你不会写,二来面试官也看不懂)
1. Queue
Python中,使用collections.deque,双端队列
1 class MyQueue: 2 # 队列初始化 3 def __init__(self): 4 self.elements = [] # 用list存储队列元素 5 self.pointer = 0 # 队头位置 6 7 # 获取队列中元素个数 8 def size(self): 9 return len(self.elements)-pointer 10 11 # 判断队列是否为空 12 def empty(self): 13 return self.size() == 0 14 15 # 在队尾添加一个元素 16 def add(self, e): 17 self.elements.append(e) 18 19 # 弹出队首元素,如果为空则返回None 20 def poll(self): 21 if self.empty(): 22 return None 23 pointer += 1 24 return self.elements[pointer-1]
2. 图的BFS
BFS中可能用到的HashSet(C++: unordered_map, Python: dict)
常用邻接表存储。邻接矩阵太大了...
邻接表定义:
1. 自定义的方法,更加工程化。所以在面试中如果时间不紧张题目不难的情况下,推荐使用自定义邻接表的方式。
1 def DirectedGraphNode: 2 def __init__(self, label): 3 self.label = label 4 self.neighbors = [] # a list of DirectedGraphNode‘s 5 ... 6 其中 neighbors 表示和该点连通的点有哪些
2. 使用 Map 和 Set
这种方式虽然没有上面的方式更加直观和容易理解,但是在面试中比较节约代码量。
1 # 假设nodes为节点标签的列表: 2 3 # 使用了Python中的dictionary comprehension语法 4 adjacency_list = {x:set() for x in nodes} 5 6 # 另一种写法 7 adjacency_list = {} 8 for x in nodes: 9 adjacency_list[x] = set() 10 其中 T 代表节点类型。通常可能是整数(Integer)。
3. 拓扑排序
http://www.lintcode.com/problem/topological-sorting/
http://www.jiuzhang.com/solutions/topological-sorting/
4. BFS模板
4.1 无需分层遍历
1 from collections import deque 2 3 queue = deque() 4 seen = set() #等价于Java版本中的set 5 6 seen.add(start) 7 queue.append(start) 8 while len(queue): 9 head = queue.popleft() 10 for neighbor in head.neighbors: 11 if neighbor not in seen: 12 seen.add(neighbor) 13 queue.append(neighbor) 14 15 16 neighbor 表示从某个点 head 出发,可以走到的下一层的节点。 17 set存储已经访问过的节点(已经丢到 queue 里去过的节点) 18 queue 存储等待被拓展到下一层的节点 19 set与 queue 是一对好基友,无时无刻都一起出现,往 queue 里新增一个节点,就要同时丢到 set 里。
4.2 需要分层遍历
1 from collections import deque 2 3 queue = deque() 4 seen = set() 5 6 seen.add(start) 7 queue.append(start) 8 while len(queue): 9 size = len(queue) 10 for _ in range(size): 11 head = queue.popleft() 12 for neighbor in head.neighbors: 13 if neighbor not in seen: 14 seen.add(neighbor) 15 queue.append(neighbor) 16 17 18 size = queue.size() 是一个必须的步骤。如果在 for 循环中使用 for (int i = 0; i < queue.size(); i++) 会出错,因为 queue.size() 是一个动态变化的值。所以必须先把当前层一共有多少个节点存在局部变量 size 中,才不会把下一层的节点也在当前层进行扩展。
1. 二叉树上的BFS
http://www.lintcode.com/problem/binary-tree-level-order-traversal/ Video 11:00
2. Binary Tree的序列化/反序列化
http://www.lintcode.com/en/help/binary-tree-representation/
http://www.lintcode.com/en/problem/binary-tree-serialization/
Binary Tree Level Order Traversal II
http://www.lintcode.com/en/problem/binary-tree-level-order-traversal-ii/
http://www.jiuzhang.com/solutions/binary-tree-level-order-traversal-ii/
Binary Tree Zigzag Order Traversal
http://www.lintcode.com/en/problem/binary-tree-zigzag-level-order-traversal/
http://www.jiuzhang.com/solutions/binary-tree-zigzag-level-order-traversal/
Convert Binary Tree to Linked Lists by Depth
http://www.lintcode.com/en/problem/convert-binary-tree-to-linked-lists-by-depth/
http://www.jiuzhang.com/solutions/convert-binary-tree-to-linked-lists-by-depth/
3. 图的BFS
http://www.lintcode.com/problem/clone-graph/ Video 43:00
http://www.lintcode.com/problem/word-ladder/ Video 55:00
4. 矩阵的bfs
图 Graph N个点,M条边 M最大是 O(N^2) 的级别 图上BFS时间复杂度 = O(N + M) ? 说是O(M)问题也不大,因为M一般都比N大 所以最坏情况可能是 O(N^2) 矩阵 Matrix R行C列 R*C个点,R*C*2 条边(每个点上下左右4条边,每条边被2个点共享)。 矩阵中BFS时间复杂度 = O(R * C)
http://www.lintcode.com/problem/number-of-islands/ Video 1:30:00
http://www.lintcode.com/problem/knight-shortest-path/ Video 1:35:00
5. 拓扑排序
入度(In-degree): 有向图(Directed Graph)中指向当前节点的点的个数(或指向当前节点的边的条数) 算法描述: 1. 统计每个点的入度 2. 将每个入度为 0 的点放入队列(Queue)中作为起始节点 3. 不断从队列中拿出一个点,去掉这个点的所有连边(指向其他点的边),其他点的相应的入度 - 1 4. 一旦发现新的入度为 0 的点,丢回队列中 拓扑排序并不是传统的排序算法 一个图可能存在多个拓扑序(Topological Order),也可能不存在任何拓扑序
拓扑排序的四种不同问法:
求任意1个拓扑序(Topological Order)
问是否存在拓扑序(是否可以被拓扑排序)
求所有的拓扑序 DFS
求是否存在且仅存在一个拓扑序 Queue中最多同时只有1个节点
http://www.lintcode.com/problem/topological-sorting/
http://www.lintcode.com/problem/course-schedule/
http://www.lintcode.com/problem/course-schedule-ii/
http://www.lintcode.com/problem/alien-dictionary/
相似问题:http://www.lintcode.com/problem/sequence-reconstruction/
? 图上的BFS ? 判断一个图是否是一棵树 ? http://www.lintcode.com/problem/graph-valid-tree/ ? 搜索图中最近值为target的点 ? http://www.lintcode.com/problem/search-graph-nodes/ ? 无向图联通块 ? http://www.lintcode.com/problem/connected-component-in-undirected-graph/ ? 序列重构(判断是否只有一个拓扑排序) ? http://www.lintcode.com/problem/sequence-reconstruction/ ? 矩阵上的BFS ? 僵尸多少天吃掉所有人 ? http://www.lintcode.com/problem/zombie-in-matrix/ ? 建邮局问题 Build Post Office II ? http://www.lintcode.com/problem/build-post-office-ii/
双向BFS
https://www.jiuzhang.com/tutorial/algorithm/371
以上是关于BFS总结的主要内容,如果未能解决你的问题,请参考以下文章