二叉树的广度优先搜索即从上到下、从左到右地进行搜索,对于层序遍历(Level Order)问题,即依次遍历第一层节点、第二层节点…等,基本可以秒杀。

广度优先搜索是通过队列来实现的,python中优先用collections.deque,因为deque的 popleft() 比列表的 pop(0) 快不少。

剑指 Offer 32 - I. 从上到下打印二叉树

import collections  # leetcode里面可以去掉,下面都省略
class Solution:def levelOrder(self, root: TreeNode) -> List[int]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:node = queue.popleft()ans.append(node.val)if node.left:  # 左子节点非空,加入队列queue.append(node.left)if node.right:  # 右子节点非空,加入队列queue.append(node.right)return ans

从根节点开始,每个节点入队之后,在出队的时候把它的左右子节点也入队(如果非空),则该队列就完成了广度优先搜索。

102. 二叉树的层序遍历 (剑指 Offer 32 - II. 从上到下打印二叉树 II)

class Solution:def levelOrder(self, root: TreeNode) -> List[List[int]]:ans = list()if not root:   # 判断空树return ansqueue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left:  # 左子节点非空,加入队列queue.append(node.left)if node.right:  # 右子节点非空,加入队列queue.append(node.right)ans.append(curLevel)return ans

需要把同一层的节点放到同一个数组中,方法是用一个当前层数组 curLevel,通过循环每次把同一层的节点的子节点全部入队,同时将这些节点的值记录到curLevel 中,一层节点遍历完之后将 curLevel 加入结果数组 ans 中。

103. 二叉树的锯齿形层序遍历(剑指 Offer 32 - III. 从上到下打印二叉树 III)

class Solution:def levelOrder(self, root: TreeNode) -> List[List[int]]:ans = list()if not root:   # 判断空树return ansqueue = collections.deque()queue.append(root)odd = True # 奇偶层标志while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left:  # 左子节点非空,加入队列queue.append(node.left)if node.right:  # 右子节点非空,加入队列queue.append(node.right)if odd:ans.append(curLevel)odd = Falseelse:ans.append(curLevel[::-1])odd = Truereturn ans

按照之字形顺序打印二叉树,只需要加个奇偶层标志即可。

1609. 奇偶树

class Solution:def isEvenOddTree(self, root: Optional[TreeNode]) -> bool:if not root:   # 判断空树return anslevel = 0queue = collections.deque()queue.append(root)while queue:curLevel = []for i in range(len(queue)):node = queue.popleft()if (level % 2 == 0 and node.val % 2 == 0) or (level % 2 != 0 and node.val % 2 != 0):return Falseelse:if len(curLevel) == 0:curLevel.append(node.val)elif (level % 2 == 0 and node.val <= curLevel[-1]) or (level % 2 != 0 and node.val >= curLevel[-1]):return FalsecurLevel.append(node.val)if node.left:  # 左子节点非空,加入队列queue.append(node.left)if node.right:  # 右子节点非空,加入队列queue.append(node.right)level += 1return True

根据所在层数的奇偶,判断节点值的奇偶以及递增或递减是否符合奇偶树的要求。

107. 二叉树的层序遍历 II

class Solution:def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)ans.append(curLevel)return ans[::-1]

唯一区别就是输出结果时倒转输出。

226. 翻转二叉树

class Solution:def invertTree(self, root: TreeNode) -> TreeNode:if not root:returnqueue = collections.deque()queue.append(root)while queue:for _ in range(len(queue)):node = queue.popleft()node.left, node.right = node.right, node.leftif node.left:queue.append(node.left)if node.right:queue.append(node.right)return root

层序遍历时,交换节点的左右子节点,就完成了翻转二叉树,用前中后序遍历的写法见这篇文章。

104. 二叉树的最大深度

class Solution:def maxDepth(self, root: Optional[TreeNode]) -> int:if not root:return 0queue = collections.deque()queue.append(root)depth = 0while queue:depth += 1for _ in range(len(queue)):node = queue.popleft()if node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth

二叉树的最大深度,就是二叉树的层数。

111. 二叉树的最小深度

class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0queue = collections.deque()queue.append(root)depth = 1while queue:for i in range(len(queue)):node = queue.popleft()if not node.left and not node.right:return depthif node.left:  # 左子节点非空,加入队列queue.append(node.left)if node.right:  # 右子节点非空,加入队列queue.append(node.right)depth += 1

只需要用depth记录层数,当遇到叶节点就返回depth,即为最小深度。

199. 二叉树的右视图

class Solution:def rightSideView(self, root: TreeNode) -> List[int]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:n = len(queue)for i in range(n):node = queue.popleft()if i == n - 1:ans.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return ans

结果需要的是每一层的最右边的数,因此循环到最右边的数时,才将节点加入结果数组 ans。

513. 找树左下角的值

class Solution:def findBottomLeftValue(self, root: TreeNode) -> int:if not root:return 0queue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return curLevel[0]

结果需要的是最底层的最左边节点的值,因此用curLevel数组记录每层的节点值,最后返回curLevel[0]就是最底层的最左边节点的值。

1302. 层数最深叶子节点的和

class Solution:def deepestLeavesSum(self, root: Optional[TreeNode]) -> int:# 题目说了非空树queue = collections.deque()queue.append(root)while queue:curLevel = 0for i in range(len(queue)):node = queue.popleft()curLevel += node.valif node.left:queue.append(node.left)if node.right:queue.append(node.right)return curLevel

返回最后一层的节点之和。

637. 二叉树的层平均值

class Solution:def averageOfLevels(self, root: TreeNode) -> List[float]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:currLevel = list()n = len(queue)for i in range(n):node = queue.popleft()currLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)ans.append(mean(currLevel))return ans

结果需要的是每一层的平均数,因此将平均数加入结果数组 ans。

515. 在每个树行中找最大值

class Solution:def largestValues(self, root: TreeNode) -> List[int]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:currLevel = list()n = len(queue)for i in range(n):node = queue.popleft()currLevel.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)ans.append(max(currLevel))return ans

结果需要的是每一层的最大数,因此将最大数加入结果数组 ans。

1161. 最大层内元素和

class Solution:def maxLevelSum(self, root: TreeNode) -> int:if not root:return 0queue = collections.deque()queue.append(root)MaxValue = -float('inf')ans = 1depth = 1while queue:curLevel = 0for i in range(len(queue)):node = queue.popleft()curLevel += node.valif node.left:queue.append(node.left)if node.right:queue.append(node.right)if curLevel > MaxValue:MaxValue = curLevelans = depthdepth += 1return ans

目标是找到层值之和最大的那一层,记录层数和最大值即可,注意 MaxValue 初始值要设成负无穷 -float(‘inf’) 。

429. N 叉树的层序遍历

"""
# Definition for a Node.
class Node:def __init__(self, val=None, children=None):self.val = valself.children = children
"""
import collections
class Solution:def levelOrder(self, root: 'Node') -> List[List[int]]:ans = list()if not root:return ansqueue = collections.deque()queue.append(root)while queue:curLevel = list()for i in range(len(queue)):node = queue.popleft()curLevel.append(node.val)for child in node.children: # 区别if child:queue.append(child)ans.append(curLevel)return ans

N叉数是 children 列表而二叉树是 left 和 right ,遍历 children 即可。

116. 填充每个节点的下一个右侧节点指针

class Solution:def connect(self, root: 'Node') -> 'Node':if not root:return rootqueue = collections.deque()queue.append(root)while queue:size = len(queue)for i in range(size):node = queue.popleft()if i < size - 1: # 必须使用 sizenode.next = queue[0]if node.left:queue.append(node.left)if node.right:queue.append(node.right)return root

层序遍历一次二叉树,记录节点是队列先进先出的,所以左边的节点先出来,它的 next 就为 queue[0],注意 len(queue) 是会变化的,所以必须使用 size 记录一层的长度

117 . 填充每个节点的下一个右侧节点指针 II

class Solution:def connect(self, root: 'Node') -> 'Node':if not root:return rootqueue = collections.deque()queue.append(root)while queue:size = len(queue)for i in range(size):node = queue.popleft()if i < size - 1:node.next = queue[0]if node.left:queue.append(node.left)if node.right:queue.append(node.right)return root

不完美的二叉树,但是和上一题一模一样的代码。

623. 在二叉树中增加一行

class Solution:def addOneRow(self, root: TreeNode, val: int, depth: int) -> TreeNode:if depth == 1:new_root = TreeNode(val = val, left = root, right = None)return new_rootqueue = collections.deque()queue.append((root, 1))while queue:for _ in range(len(queue)):node, d = queue.popleft()if d == depth - 1:old_left = node.leftold_right = node.rightnode.left = TreeNode(val = val, left = old_left, right = None)node.right = TreeNode(val = val, left = None, right = old_right)else:if node.left:queue.append((node.left, d+1))if node.right:queue.append((node.right, d+1))return root

如果在第一行增加,那就是创建一个新的根节点,然后将原根节点作为左子节点。否则的话,就在队列中使用多一个参数 d 来记录深度,在 d - 1 层进行增加一行的操作,先记住节点原来的左右子节点 old_left 与 old_right,然后创建新的节点即可。关键是必须使用 for 循环,对整个第 d - 1 层都进行同样的操作。

662. 二叉树最大宽度

class Solution:def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int:ans = 1if not root:return 0queue = collections.deque()queue.append((root, 1))while queue:cur = []for _ in range(len(queue)):node, pos = queue.popleft()cur.append(pos)if node.left:queue.append((node.left, 2 * pos - 1))if node.right:queue.append((node.right, 2 * pos))if max(cur) - min(cur) + 1 > ans:ans = max(cur) - min(cur) + 1return ans

在队列中使用多一个参数 pos 来记录位置,只需要记住的是,位置为 pos 的节点(从 1 开始)的左子节点位置是 2 * pos - 1,右子节点的位置是 2 * pos。

958. 二叉树的完全性检验

class Solution:def isCompleteTree(self, root: TreeNode) -> bool:queue = collections.deque()queue.append((root, 1))depth = 0while queue:if len(queue) == 2**depth:for i in range(len(queue)):node, pos = queue.popleft()if node.left:queue.append((node.left, pos*2-1))if node.right:queue.append((node.right, pos*2))depth += 1else:for i in range(len(queue)):node, pos = queue.popleft()if node.left or node.right or (i+1) != pos:return Falsereturn True

与上一题类似的,关键是记录节点的位置(注意位置从 1 开始)。在满层中正常遍历,一旦遇到不满的层,如果其中有非叶子节点或者位置对不上则不是完全二叉树。

993. 二叉树的堂兄弟节点

class Solution:def isCousins(self, root: TreeNode, x: int, y: int) -> bool:# x 和 y 的深度与父节点x_depth, x_parent, y_depth, y_parent = None, None, None, None level = 0queue = collections.deque([(root, None)])while queue:n = len(queue)level += 1for i in range(n):node, node_parent = queue.popleft()# 每个节点的值都是唯一的if node.val == x:x_depth = levelx_parent = node_parentif node.val == y:y_depth = levely_parent = node_parentif node.left:queue.append((node.left, node))if node.right:queue.append((node.right, node))return x_depth == y_depth and x_parent != y_parent

由于题目中说明每个节点的值都是唯一的,所以用四个变量分别表示 x 和 y 的深度与父节点。然后在队列中要同时记录节点和节点的父节点,如果遇到值为 x 或 y 的节点就记录其深度和父节点,最后进行比较即可。

二叉树层序遍历(广度优先搜索)基础概念与经典题目(Leetcode题解-Python语言)相关推荐

  1. 二叉树的遍历—广度优先(BFS)和深度优先(DFS)python实现

    二叉树 二叉树(Binary tree)是树形结构的一个重要类型.对于二叉树的基础知识这里不做过多介绍,下面我们直接介绍二叉树的遍历方式和如何用python代码去实现二叉树的遍历. 二叉树的遍历(重点 ...

  2. 岛屿类问题的广度优先深度优先双解法(Leetcode题解-Python语言)

    695. 岛屿的最大面积 先上最经典的题目,详细思路看这题的官方题解,简单来说的岛屿问题就是遍历二维数组,一般都是从一块陆地开始,进行深度优先或者广度优先搜索,每次上下左右四个方向选其一然后寻找下一块 ...

  3. 高度平衡的二叉搜索树基础概念与经典题目(Leetcode题解-Python语言)

    高度平衡的二叉搜索树(平衡二叉树),定义见此Leetbook.简单来说,就是基于相同节点值构建出来的二叉搜索树中高度最小的,即为平衡二叉树(不唯一).有 N 个节点的平衡二叉搜索树,它的高度是 log ...

  4. 栈的基础概念与经典题目(Leetcode题解-Python语言)

    栈是先入后出(后入先出)的数据结构,常用操作就 push 和 pop,Python中用列表实现即可,基本概念可以看Leetbook相关章节. 普通栈 232. 用栈实现队列 class MyQueue ...

  5. 二分查找基础概念与经典题目(Leetcode题解-Python语言)二分数值型

    二分查找的讲解请见上一篇文章.本文主要记录对数值进行二分的题目解法与思路. 374. 猜数字大小 class Solution:def guessNumber(self, n: int) -> ...

  6. 哈希表(散列表)基础概念与经典题目(Leetcode题解-Python语言)之中——实际应用

    上一节介绍了哈希表的原理与设计方法,这一节则直接python中现有的哈希表类型:哈希集合 set(集合)和哈希映射 dict(字典)来解决实际应用(刷题). 零.概念 在介绍实际应用之前,有一个概念我 ...

  7. 链表基础概念与经典题目(Leetcode题解-Python语言)

    所谓链表,就是由链节点元素组成的表,那什么是链节点呢?直接上定义: class ListNode:def __init__(self, val=0, next=None):self.val = val ...

  8. 二分查找基础概念与经典题目(Leetcode题解-Python语言)二分索引型

    二分查找的定义如下(引自Wiki): 在计算机科学中,二分查找算法(英语:binary search algorithm),也称折半搜索算法(英语:half-interval search algor ...

  9. 哈希表(散列表)基础概念与经典题目(Leetcode题解-Python语言)之下——设计键

    在很多应用中,我们会发现某种映射关系(模式),但它并不是简单一 一对应的.这时,我们就要从键 key 入手,通过设计合适的键,建立映射关系.leetbook的这个章节总结了一些常见的键,以供参考. 4 ...

最新文章

  1. mysql数字字符串教程_很全面的mysql字符串函数的教程
  2. iOS获取已安装的app列表(私有库)+ 通过包名打开应用
  3. 开发函数计算的正确姿势 —— 移植 next.js 服务端渲染框架
  4. 2017.10.12 礼物(zjoi2011) 失败总结
  5. “腾讯持股比例提升”系误读!美团对外定增后腾讯持股比例降低
  6. 邮件服务器IMail教程(2)
  7. Win7 下安装流程图绘制软件 Dia
  8. ibus五笔快捷键 繁简 单字 词组切换
  9. 5种Python深度学习库和资料
  10. python3.6 scrapy模块查询POS后台获取指定时间和状态的订单存入到excel表格中
  11. linux 好书推荐
  12. 【Flutter】Dart 数据类型 布尔类型 ( 布尔类型定义 | 逻辑运算 )
  13. vue 引入 element-ui 报 es2015 的错
  14. (转)汇编bne的问题
  15. 阿里天池比赛——食物声音识别
  16. 《易中天中华史 - 第五卷 从春秋到战国》读书笔记
  17. 2022第三届全国大学生网络安全精英赛练习题(2)
  18. bochs linux 安装软件,bochs linux镜像
  19. OpenMV物品清单
  20. java打地鼠游戏教案,幼儿园打地鼠游戏教案

热门文章

  1. PHP开发常见功能实现流程
  2. PHP-高并发和大流量的解决方案
  3. 【遥感数字图像处理】实验:Erdas 软件的认识与使用
  4. Android之解决androidx.appcompat.widget.Toolbar去掉左边距
  5. 递归和非递归实现规律函数
  6. 关于nginx为站点绑定域名以及绑定多个域名
  7. 3500个常用汉字表_小学常用560个汉字笔画笔顺表,打印下来,小学六年慢慢练...
  8. html的canvas标签用法,html5中关于canvas标签用法(绘图)
  9. java爬虫工具xpath提取,2020-07-16--爬虫数据提取--xpath
  10. 那些年,画家发明的黑科技