BFS
简单
1、111. 二叉树的最小深度 https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/
考点:
1、一层一层遍历,直到满足要求
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
global result
result = None
def helper(cur_list, layer):
global result
tmp = []
for cur in cur_list:
# 叶子节点
if cur.left == None and cur.right == None:
result = layer
return
if cur.left:
tmp.append(cur.left)
if cur.right:
tmp.append(cur.right)
helper(tmp, layer+1)
start = []
start.append(root)
helper(start, 1)
return result
2、559. N叉树的最大深度 https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/
考点:(同上)
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
global result
result = 0
def helper(last_list, layer):
next_list = []
for cur in last_list:
for child in cur.children:
if child:
next_list.append(child)
if not next_list:
global result
result = layer
return
helper(next_list, layer+1)
if not root:
return 0
helper([root], 1)
return result
3、剑指 Offer 32 - II. 从上到下打印二叉树 II https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/
考点:
1、BFS,从上到下 从左到右打印节点
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
result = []
def bfs(cur_list):
next_list = []
cur_val = []
for cur in cur_list:
if cur:
cur_val.append(cur.val)
next_list.append(cur.left)
next_list.append(cur.right)
if cur_val:
result.append(cur_val)
if next_list:
bfs(next_list)
bfs([root])
return result
3、993. 二叉树的堂兄弟节点 https://leetcode-cn.com/problems/cousins-in-binary-tree/
考点:
1、需要考虑二叉树层数关系,使用BFS
2、判断堂兄弟关系,引入一个列表表示当前已经遍历过的堂兄弟
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def check(self, cur, old_val, x, y):
if cur.left and ((x == cur.left.val and y in old_val) or (y == cur.left.val and x in old_val) ):
return True
if cur.right and ((x == cur.right.val and y in old_val) or (y == cur.right.val and x in old_val) ):
return True
def refresh_old_val(self, cur, old_val, next_list):
if cur.left:
old_val.append(cur.left.val)
next_list.append(cur.left)
if cur.right:
old_val.append(cur.right.val)
next_list.append(cur.right)
def isCousins(self, root: TreeNode, x: int, y: int) -> bool:
global result
result = False
def bfs(cur_list):
next_list = []
old_val = []
for cur in cur_list:
cur_children = []
if self.check(cur, old_val, x, y):
global result
result = True
return
self.refresh_old_val(cur, old_val, next_list)
if next_list:
bfs(next_list)
bfs([root])
return result
4. 690. 员工的重要性 https://leetcode-cn.com/problems/employee-importance/
考点:
1、引入字典数据结构,便于查找
2、每个递归生成新的列表,用于BFS查找
"""
# Definition for Employee.
class Employee:
def __init__(self, id: int, importance: int, subordinates: List[int]):
self.id = id
self.importance = importance
self.subordinates = subordinates
"""
class Solution:
def getImportance(self, employees: List['Employee'], id: int) -> int:
global imports
imports = 0
child_employ = []
employ_dict = {}
# get employ
for employ in employees:
employ_dict[employ.id] = employ
def bfs(employees_list):
global imports
next_employee_list = []
for employ in employees_list:
imports += employ_dict[employ].importance
if employ_dict[employ].subordinates:
next_employee_list.extend(employ_dict[employ].subordinates)
if next_employee_list:
bfs(next_employee_list)
# get child employ
bfs([id])
return imports
5.剑指 Offer 32 - III. 从上到下打印二叉树 III https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/
考点:
1、典型BFS
2、引入一个boolen变量标志当前行打印正序还是逆序
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
result = []
global left_right
left_right = True
def bfs(layer_list):
layer_result = []
next_list = []
for layer in layer_list:
layer_result.append(layer.val)
if layer.left:
next_list.append(layer.left)
if layer.right:
next_list.append(layer.right)
global left_right
if left_right:
result.append(layer_result)
left_right = False
else:
layer_result.reverse()
result.append(layer_result)
left_right = True
if next_list:
bfs(next_list)
if not root:
return []
bfs([root])
return result
6. 剑指 Offer 32 - I. 从上到下打印二叉树 https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/
考点:
1、bfs遍历二叉树每一层
2、需要考虑输入为空树情况
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
result = []
def bfs(layer_list):
layer_result = []
next_layer = []
for layer in layer_list:
layer_result.append(layer.val)
if layer.left:
next_layer.append(layer.left)
if layer.right:
next_layer.append(layer.right)
result.extend(layer_result)
if next_layer:
bfs(next_layer)
if not root:
return []
bfs([root])
return result
7、542. 01 矩阵 https://leetcode-cn.com/problems/01-matrix/
考点
1、按照先设置距离为0的所有位置,然后BFS找所有距离为1的位置,一直迭代下去
2、注意,生成二维数组,不能使用[-1] * col * row, 应该使用 [[-1] * col for i in range(row)] 生成二维数据
class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
row = len(matrix)
col = len(matrix[0])
result = [[-1] * col for i in range(row)]
global result_rest
result_rest = row * col
zero_list = []
# print(result)
# 初始化数组
for i in range(row):
for j in range(col):
if matrix[i][j] == 0:
# print(i, j)
zero_list.append((i, j))
result[i][j] = 0
result_rest -= 1
# print(result)
# print(result)
def bfs(layer_list, val):
global result_rest
# print(result)
if result_rest == 0:
return
next_list = []
for layer in layer_list:
i, j = layer
for ii, jj in [(i+1, j), (i-1, j), (i, j-1), (i, j+1)]:
if 0 <= ii < row and 0 <= jj < col and result[ii][jj] == -1:
result[ii][jj] = val + 1
next_list.append((ii, jj))
# global result_rest
result_rest -= 1
bfs(next_list, val + 1)
bfs(zero_list, 0)
# print(result)
return result
8、279. 完全平方数 https://leetcode-cn.com/problems/perfect-squares/
考点:
1、计算最小值,迭代后面值由前面值 确定,可以使用动态规划作态
2、同时 该类问题可以考虑使用BFS,即计算每步结果的列表,当结果列表有最终结果,返回结果即可
class Solution:
def numSquares(self, n: int) -> int:
selected_num = []
for i in range(1, int(n ** 0.5)+1):
selected_num.append(i ** 2)
print(selected_num)
global result
result = n
if n in selected_num:
return 1
def bfs(cur_list, cur_layer):
next_list = set()
for selected in selected_num:
for cur in cur_list:
next_list.add(selected + cur)
if n in next_list:
global result
result = cur_layer + 1
return
else:
bfs(next_list, cur_layer + 1)
bfs(selected_num, 1)
return result
9.863. 二叉树中所有距离为 K 的结点 https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/
考点:
1、BFS和DFS结合使用
2、计算出每个层次距离为1的关系字典表,然后 使用DFS计算响应距离为K的路径
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def distanceK(self, root: TreeNode, target: TreeNode, K: int) -> List[int]:
relation = collections.defaultdict(list)
def bfs(cur_list):
next_list = []
for cur in cur_list:
if cur.left:
relation[cur.val].append(cur.left.val)
relation[cur.left.val].append(cur.val)
next_list.append(cur.left)
if cur.right:
relation[cur.val].append(cur.right.val)
relation[cur.right.val].append(cur.val)
next_list.append(cur.right)
if next_list:
bfs(next_list)
bfs([root])
result = []
def dfs(cur_list, step):
if step == K:
result.append(cur_list[-1])
if relation.get(cur_list[-1]):
for next_node in relation.get(cur_list[-1]):
if next_node not in cur_list:
new_cur_list = list(cur_list)
new_cur_list.append(next_node)
dfs(new_cur_list, step + 1)
dfs([target.val], 0)
return result
10.513. 找树左下角的值 https://leetcode-cn.com/problems/find-bottom-left-tree-value/
考点:
1、BFS遍历,知道都没有子节点
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
def bfs(cur_list):
next_list = []
for cur in cur_list:
# print(cur.val)
if cur.left:
next_list.append(cur.left)
if cur.right:
next_list.append(cur.right)
if not next_list:
# print("%%", cur_list[0])
return cur_list[0]
else:
return bfs(next_list)
if not root:
return None
return bfs([root]).val
11、1391. 检查网格中是否存在有效路径 https://leetcode-cn.com/problems/check-if-there-is-a-valid-path-in-a-grid/
12、 1519. 子树中标签相同的节点数 https://leetcode-cn.com/problems/number-of-nodes-in-the-sub-tree-with-the-same-label/submissions/
考点:
1、先使用BFS建立单层关系,然后使用BFS查找更深层次关系,结果显示 时间超时
class Solution:
def countSubTrees(self, n: int, edges: List[List[int]], labels: str) -> List[int]:
relation = collections.defaultdict(list)
def bfs(cur_list):
if len(edges) == 0:
return
next_list = []
for cur in cur_list:
for edge in list(edges):
if cur == edge[0]:
next_list.append(edge[1])
edges.remove(edge)
relation[cur].append(edge[1])
elif cur == edge[1]:
next_list.append(edge[0])
edges.remove(edge)
relation[cur].append(edge[0])
if next_list:
bfs(next_list)
# 建立22之间关系
bfs([0])
def bfs_time(cur_list):
next_list = []
for cur in cur_list:
if relation[cur]:
# print(relation[cur], relation[cur])
next_list.extend(relation[cur])
if next_list:
next_list.extend(bfs_time(next_list))
return next_list
# BFS计算子树次数
result = [1] * n
for i in range(n):
result[i] = bfs_time([i])
# print(result)
# 计算重复个数
index_value = {}
for i in range(n):
index_value[i] = labels[i]
# print(index_value)
real_result = [1] * n
for i in range(n):
compare_value = index_value[i]
tmp = 0
for j in result[i]:
if compare_value == index_value[j]:
tmp += 1
real_result[i] += tmp
return real_result
13、515. 在每个树行中找最大值 https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/
考点:
1、bfs遍历每一层
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def largestValues(self, root: TreeNode) -> List[int]:
result = []
def bfs(cur_list):
next_list = []
for cur in cur_list:
if cur.left:
next_list.append(cur.left)
if cur.right:
next_list.append(cur.right)
if next_list:
value = [next_v.val for next_v in next_list]
result.append(max(value))
bfs(next_list)
if not root:
return []
result.append(root.val)
bfs([root])
return result
14、 752. 打开转盘锁 https://leetcode-cn.com/problems/open-the-lock/
考点:
1、该题为求最大值最小值,后一状态由前一状态推到出,可以想到使用动态规划做
2、该题我们同样考虑使用BFS来做,计算每步能得到所有字符串列表,当列表有目标字符串,则返回结果
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
history = []
global result
result = -1
relation = {"0": ("1", "9"),
"1": ("0", "2"),
"2": ("1", "3"),
"3": ("2", "4"),
"4": ("3", "5"),
"5": ("4", "6"),
"6": ("5", "7"),
"7": ("6", "8"),
"8": ("7", "9"),
"9": ("8", "0")}
def change(string):
# 变化各位置
result = []
for i in range(4):
# print(string[i])
k, l = relation[string[i]]
result.append(string[0:i]+k+string[i+1:])
result.append(string[0:i]+l+string[i+1:])
return result
def bfs(cur_list, step):
# print(cur_list, step)
if target in cur_list:
global result
result = step
return
next_list = []
for cur in cur_list:
change_strs = change(cur)
for change_str in change_strs:
if change_str not in history and change_str not in deadends:
next_list.append(change_str)
history.append(change_str)
if next_list:
bfs(next_list, step + 1)
if "0000" in deadends:
return -1
bfs(["0000"], 0)
return result
上面答案会出现超限时间限制,这里有一个技巧,把代码中的list替换成set,通过
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
history = set(deadends)
global result
result = -1
relation = {"0": ("1", "9"),
"1": ("0", "2"),
"2": ("1", "3"),
"3": ("2", "4"),
"4": ("3", "5"),
"5": ("4", "6"),
"6": ("5", "7"),
"7": ("6", "8"),
"8": ("7", "9"),
"9": ("8", "0")}
def change(string):
# 变化各位置
result = []
for i in range(4):
# print(string[i])
k, l = relation[string[i]]
result.append(string[0:i]+k+string[i+1:])
result.append(string[0:i]+l+string[i+1:])
return result
def bfs(cur_list, step):
# print(cur_list, step)
if target in cur_list:
global result
result = step
return
next_list = []
for cur in cur_list:
change_strs = change(cur)
for change_str in change_strs:
if change_str not in history:
next_list.append(change_str)
history.add(change_str)
if next_list:
bfs(next_list, step + 1)
if "0000" in deadends:
return -1
bfs(["0000"], 0)
return result
15、994. 腐烂的橘子 https://leetcode-cn.com/problems/rotting-oranges/
考点:
1、典型的BFS题型,计算每一遍腐烂之后的苹果状态
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
all_bad = []
all_good = []
row = len(grid)
col = len(grid[0])
for i in range(row):
for j in range(col):
if grid[i][j] == 1:
all_good.append((i, j))
elif grid[i][j] == 2:
all_bad.append((i, j))
# print(all_bad, all_good)
def bfs(bad_list, step):
next_list = []
for bad in bad_list:
i, j = bad
for ii, jj in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
if 0 <= ii < row and 0 <= jj < col and (ii, jj) in all_good:
next_list.append((ii, jj))
all_good.remove((ii, jj))
if next_list:
return bfs(next_list, step+1)
return step
step = bfs(all_bad, 0)
return -1 if all_good else step
15、126. 单词接龙 II
考点:
1、修改一个字符,即字符窜的某个字符为*,所以先对所有字符窜 生成 dict,key为某个匹配到全字符窜
2、使用BFS,计算每步可得到的字符窜,然后就超时了
3、注意,history使用set比使用list 效率高
4、每步使用pattern 表示已经跑过的类型, 如果已经跑过了,该类型的字符窜就肯定在结果列表里面,后续就不用跑该类型(剪枝)
class Solution:
def findLadders(self, beginWord, endWord, wordList):
word_dict = collections.defaultdict(list)
for word in wordList:
for i in range(len(word)):
word_dict[word[:i] + "*" + word[i+1:]].append(word)
global hist
hist = set()
def bfs(cur_lists, step):
global hist
next_list = []
bfs_result = []
for cur_list in cur_lists:
if endWord in cur_list:
bfs_result.append(cur_list)
if bfs_result:
return bfs_result
tmp_history = set()
for cur_list in cur_lists:
for i in range(len(cur_list[-1])):
pattern = cur_list[-1][:i] + "*" + cur_list[-1][i+1:]
if pattern not in hist:
next_words = word_dict.get(pattern)
if next_words:
for word in next_words:
if word not in cur_list:
new_cur_list = list(cur_list)
new_cur_list.append(word)
next_list.append(new_cur_list)
tmp_history.add(pattern)
hist = hist.union(tmp_history)
print("-", hist)
if next_list:
return bfs(next_list, step+1)
else:
return []
return bfs([[beginWord]], 0)
16、210. 课程表 II
考点:
1、BFS,一层一层选取当前学习的课程
2、引入课表list,表示当前的依赖课程数目,当依赖的课程数目为0,就可以加到学习顺序列表中; 同时更新被依赖课程的课表list
class Solution:
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
rela = [0] * numCourses
relationed = collections.defaultdict(list)
for prerequisite in prerequisites:
i, j = prerequisite[0], prerequisite[1]
rela[i] += 1
relationed[j].append(i)
# print(rela, relationed)
result = []
def bfs():
try:
next_course = rela.index(0)
result.append(next_course)
rela[next_course] = -1
rela_delete = relationed[next_course]
if rela_delete:
for course in rela_delete:
rela[course] -= 1
# print(rela, relationed)
except:
return
bfs()
bfs()
return result if len(result) == numCourses else []
17、
考点:
1、先找出所有1的点; 然后使用BFS,一层一层找到连在一起的岛屿, 然后然后就超时了
class Solution:
def numIslands(self, grid):
# get all iland
row = len(grid)
col = len(grid[0])
ilands = []
for i in range(row):
for j in range(col):
if grid[i][j] == "1":
ilands.append((i, j))
print(ilands)
def bfs(cur_list):
print(cur_list)
next_list = []
for cur in cur_list:
i, j = cur
for ii, jj in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
if 0 <= ii < row and 0 <= jj < col and grid[ii][jj] == "1"\
and (ii, jj) not in included:
next_list.append((ii, jj))
included.append((ii, jj))
if next_list:
bfs(next_list)
included = []
nums = 0
for iland in ilands:
if iland not in included:
included.append(iland)
nums += 1
# 扩展岛屿
bfs([iland])
return nums
老套路,把list转成set
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
# get all iland
row = len(grid)
col = len(grid[0])
ilands = []
for i in range(row):
for j in range(col):
if grid[i][j] == "1":
ilands.append((i, j))
def bfs(cur_list):
next_list = []
for cur in cur_list:
i, j = cur
for ii, jj in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
if 0 <= ii < row and 0 <= jj < col and grid[ii][jj] == "1"\
and (ii, jj) not in included:
next_list.append((ii, jj))
included.add((ii, jj))
if next_list:
bfs(next_list)
included = set()
nums = 0
for iland in ilands:
if iland not in included:
included.add(iland)
nums += 1
# 扩展岛屿
bfs([iland])
return nums
考点:
1、由于graph.length最大12,尝试对每一个节点开始,然后使用BFS一层一层路径遍历,然后就超时了
class Solution:
def shortestPathLength(self, graph: List[List[int]]) -> int:
# 由于graph.length比较小,使用BFS遍历
n = len(graph)
global min_result, result
min_result = n * 2
result = None
def bfs(cur_lists):
# print(cur_lists)
next_list = []
for cur_list in cur_lists:
if len(set(cur_list)) == n:
global min_result, result
if min_result > len(cur_list):
min_result = len(cur_list)
result = cur_list
# print("****************", cur_list)
return cur_list
last_pos = cur_list[-1]
next_pos = list(graph[last_pos])
# print("-", cur_list)
# print(next_pos)
if len(next_pos) >=2 and len(cur_list) >=2 and cur_list[-2] in next_pos:
next_pos.remove(cur_list[-2])
# print(next_pos)
for next_p in next_pos:
new_cur_list = list(cur_list)
new_cur_list.append(next_p)
next_list.append(new_cur_list)
if next_list:
bfs(next_list)
# start with i
for i in range(n):
# print("++++++++++++++", i)
bfs([[i]])
# print("&", result)
return min_result-1
继续优化,让遍历的层数 大于当前算出来的最小值,直接return, 时间超时,还差2个用例
class Solution:
def shortestPathLength(self, graph: List[List[int]]) -> int:
# 由于graph.length比较小,使用BFS遍历
n = len(graph)
global min_result, result
min_result = n * 2
result = None
def bfs(cur_lists):
# print(cur_lists)
next_list = []
for cur_list in cur_lists:
if len(set(cur_list)) == n:
global min_result, result
if min_result > len(cur_list):
min_result = len(cur_list)
result = cur_list
# print("****************", cur_list)
return cur_list
if len(cur_list) >= min_result:
return
last_pos = cur_list[-1]
next_pos = list(graph[last_pos])
# print("-", cur_list)
# print(next_pos)
if len(next_pos) >=2 and len(cur_list) >=2 and cur_list[-2] in next_pos:
next_pos.remove(cur_list[-2])
# print(next_pos)
for next_p in next_pos:
new_cur_list = list(cur_list)
new_cur_list.append(next_p)
next_list.append(new_cur_list)
if next_list:
bfs(next_list)
# start with i
for i in range(n):
# print("++++++++++++++", i)
bfs([[i]])
# print("&", result)
return min_result-1
继续优化,
19、
93. 复原IP地址
考点:
1、使用BFS,执行4个step之后,然后获取满足要求的结果(包含4组数据, 字符窜遍历到最后了)
class Solution:
def restoreIpAddresses(self, s):
if len(s) < 4:
return []
# 返回值0:为正常,1为异常,且没有必要继续(超255,格式异常如001)
def check(str):
if str.startswith("0"):
if str == "0":
return 0
else:
return 1
elif 0 < int(str) <= 255:
return 0
else:
return 1
result = []
def bfs(cur_list, step):
next_list = []
for cur in cur_list:
cur_str, start_index = cur
if start_index < len(s):
for i in range(start_index+1, len(s)+1):
next_str = s[start_index:i]
if check(next_str) == 0:
next_list.append((cur_str + "." +next_str, i))
else:
break
print(cur_list, step)
if step == 3:
for next in next_list:
next_str, next_index = next
if next_index == len(s) and next_str.count(".") == 4:
result.append(next_str[1:])
elif next_list:
bfs(next_list, step+1)
bfs([('', 0)], 0)
return result

浙公网安备 33010602011771号