一、算法框架


queue = [起始点] # 队列实现BFSvisited = set() # 记录访问过的元素点,避免“回头”访问,陷入循环visited.add(起始点)step = 0while queue:# 将所有节点同时向前扩散一步for _ in range(len(queue)):cur = queue.pop(0)if 找到目标:return 结果# 将cur的【所有相邻且没被访问过的节点】加入队列for near in cur的邻近节点:if near not in visited:queue.append(near)visited.add(near)step += 1 # 记录路径长度
def BFS(start, target):queue = collections.deque() # 核心数据结构-队列visited = set() # 记录走过的路径,避免走回头路--使用集合,检索速度更快queue.append(start) # 将起点加入队列visited.add(start)step = 0 # 记录扩散的步数while queue:size = len(queue)for i in range(size): # 将当前队列中的所有节点向四周扩散cur = queue.popleft()if cur == target: # 判断是否到终点return stepfor node in cur: # ???这里感觉代码不对,将cur的相邻节点加入队列if node not in visited:queue.append(node)visited.add(node)step += 1 # 更新步数return step
⼆、⼆叉树的最⼩⾼度
https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/

if not node.left and not node.right:
(下面的代码缺了扩散那一步,但是二叉树只有两个结点,同时按顺序出栈的,所以在循环过程中就已经扩散了)
class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0from collections import dequeq = deque([(root, 1)]) # root本身是1层,初始化为1while q:node, depth = q.popleft()if not node.left and not node.right:return depthif node.left:q.append((node.left, depth + 1))if node.right:q.append((node.right, depth + 1))return 0
三、解开密码锁的最少次数


# 将 s[j] 向上拨动一次def up(self, s:str, i:int) -> str:s_list = list(s)if s_list[i] == '9':s_list[i] = '0'else:s_list[i] = str(int(s_list[i]) + 1)return "".join(s_list)# 将 s[i] 向下拨动一次def down(self, s:str, i:int) -> str:s_list = list(s)if s_list[i] == '0':s_list[i] = '9'else:s_list[i] = str(int(s_list[i]) - 1)return "".join(s_list)def openLock(self, deadends: List[str], target: str) -> int:# BFSqueue = ['0000']visited = set()visited.add('0000')step = 0while queue:for _ in range(len(queue)): # 向周围扩散cur = queue.pop(0)# 判断是否到达终点for i in range(4): # 将当前cur元素的所有邻近元素加入队列和visitedup = self.up(cur, i)queue.append(up)visited.add(up)down = self.down(cur, i)queue.append(down)visited.add(down)step += 1return -1

def openLock(self, deadends: List[str], target: str) -> int:# BFSqueue = ['0000']visited = set()visited.add('0000')deadset = set(deadends)step = 0while queue:for _ in range(len(queue)):cur = queue.pop(0)if cur in deadset:continue # 如果cur是死亡数字,则不选这条路径if cur == target:return step # 如果cur = target,则找到目标,返回step# 将当前cur元素的所有邻近元素加入队列和visitedfor i in range(4):up = self.up(cur, i)if up not in visited:queue.append(up)visited.add(up)down = self.down(cur, i)if down not in visited:queue.append(down)visited.add(down)step += 1return -1
四、双向 BFS 优化


def openLock(self, deadends: List[str], target: str) -> int:# 双向BFS,用集合记录两边的扩散,set效率比list高,便于判断是否发生交集q1 = set()q1.add('0000')q2 = set()q2.add(target)visited = set()deadset = set(deadends)step = 0while q1 and q2:if len(q1) > len(q2): # 选择⼀个较⼩的集合进⾏扩散,效率就会⾼⼀ 些q1, q2 = q2, q1temp = set() # 记录扩散的结点for cur in q1:if cur in deadset:continueif cur in q2: # 如果两边扩散的元素出现交集,说明找到了最短路径return stepvisited.add(cur)for i in range(4):up = self.up(cur, i)if up not in visited:temp.add(up)down = self.down(cur, i)if down not in visited:temp.add(down)step += 1# 交换q1和q2,q2存储着上一次q1扩散的结果tempq1 = q2q2 = temp # q2始终记录上一次扩散时得到的元素return -1




