广度优先算法(BFS)-python

二叉树的层序遍历



前言

DFS(深度优先搜索)和 BFS(广度优先搜索)就像孪生兄弟,提到一个总是想起另一个。然而在实际使用中,我们用 DFS 的时候远远多于 BFS。

然而有两个场景:「层序遍历」、「最短路径」,使用BFS会比DFS更易于理解;

广度优先遍历是按层层递进的方式,遍历每一层的节点,即从上到下,先把每一层遍历完之后再遍历一下一层。leetcode102 二叉树的层次遍历要求的是返回每一层的节点值,所以用广度优先来做非常合适。

😃广度优先需要用队列作为辅助结构,我们先将根节点放到队列中,然后不断遍历队列。(注意,其实DFS 也用到了队列,只是在递归中“隐藏”起来了)
(本章主要讲 层次遍历)


一、题目描述

lc102 二叉树的层次遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)
在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

二、代码

2.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 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

2.2 递归解法

来自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

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小杜在学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值