DFS(深度优先搜索)和 BFS(广度优先搜索)就像孪生兄弟,提到一个总是想起另一个。然而在实际使用中,我们用 DFS 的时候远远多于 BFS。
然而有两个场景:「层序遍历」、「最短路径」,使用BFS会比DFS更易于理解;
广度优先遍历是按层层递进的方式,遍历每一层的节点,即从上到下,先把每一层遍历完之后再遍历一下一层。leetcode102 二叉树的层次遍历要求的是返回每一层的节点值,所以用广度优先来做非常合适。
广度优先需要用队列作为辅助结构,我们先将根节点放到队列中,然后不断遍历队列。(注意,其实DFS 也用到了队列,只是在递归中“隐藏”起来了)
(本章主要讲 层次遍历)
lc102 二叉树的层次遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
代码如下(示例):
# 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 levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
res = [] #存放最终的结果
queue = [root] #存储当前层的节点,这个相当于队列,先进先出,后进后出
while queue: #当当前层没有节点时,退出循环
n = len(queue) # 获取当前队列的长度,这个长度相当于 当前这一层的节点个数,以区分来自那一层
temp = [] #暂存,在while的循环中,别写在下面的for循环中!
for i in range(n): #遍历当前层的节点数
a = queue.pop(0) #推出去,将queue中存的上一层的节点全部pop出去
temp.append(a.val)
#将下一层的节点(左右)添加到queue中,以进行下一次迭代(循环)
if a.left:
queue.append(a.left)
if a.right:
queue.append(a.right)
res.append(temp)
return res
来自lc上大佬解法
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
res = []
def dfs(index,r): #index表示当前的第index层
# 假设res是[ [3],[9,20] ], index是3,就再插入一个空list放到res中
if len(res)<index:
res.append([])
# 将当前节点的值加入到res中,index代表当前层,假设index是3,节点值是99
# res是[ [3],[9,20], [15] ],加入后res就变为 [ [3],[9,20],[15,7] ]
res[index-1].append(r.val)
# 递归的处理左子树,右子树,同时将层数index+1
if r.left:
dfs(index+1,r.left)
if r.right:
dfs(index+1,r.right)
dfs(1,root)
return res
总的来说,层次遍历用BFS比DFS容易理解的多
类似题目 JZ-Office32
JZ32 III
拓展:
JZ 32III中,要求第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
可以设置一个flag = 1,每输出一次temp,则对flag取反一次
代码如下:
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
queue = [root]
res = []
flag = 1
while queue:
n = len(queue)
temp = []
for _ in range(n):
a = queue.pop(0)
temp.append(a.val)
if a.left:
queue.append(a.left)
if a.right:
queue.append(a.right)
if flag > 0:
res.append(temp)
flag = - flag
else:
res.append(temp[::-1])
flag = - flag
return res