浅析二叉树的层次遍历和最大深度

开发 前端
在讲解二叉树的时候,提到二叉树的遍历除了前中后序遍历,还有层次遍历。前中后序这三种遍历方法以及可以通过递归的方式实现了,那么今天就来讲讲层次遍历吧!

 [[375572]]

在讲解二叉树的时候,提到二叉树的遍历除了前中后序遍历,还有层次遍历。

前中后序这三种遍历方法以及可以通过递归的方式实现了,那么今天就来讲讲层次遍历吧!

LeetCode 第 102题:二叉树的层次遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。(即逐层地,从左到右访问所有节点)。

  1. 示例:  
  2. 二叉树:[3,9,20,null,null,15,7],  
  3. #     3 
  4. #   / \ 
  5. #  9  20 
  6. #    /  \ 
  7. #   15   7 
  8. 返回其层次遍历结果:  
  9.  [3], 
  10.  [9,20], 
  11.  [15,7] 

对于这道二叉树题目,我们要遍历每一层的每一个节点,可以考虑分别用BFS(广度优先搜索)和DFS(深度优先搜索)来解决,下面先简单介绍BFS,后续文章继续深入。

有两种通用的遍历树的策略:

深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点的所在边都己被探寻过,搜索将回溯到发现节点的那条边的起始节点。

深度优先搜索策略又可以根据根节点、左孩子和右孩子的相对顺序被细分为先序遍历,中序遍历和后序遍历。

宽度优先搜索算法(又称广度优先搜索 英语:Breadth-First Search, 简称BFS )

我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到,最短路径问题常用此算法。

本题就是用广度优先搜索,对二叉树按照层进行搜索,搜索逻辑如下图所示:


根据我们熟悉的BFS搜索方法,二叉树的层次遍历,关键要用到队列,父结点出,就要判断子结点是否为空,非空则马上进入队列,类似广度优先queue队列。

把每个没有搜索到的点依次放入队列,然后再弹出队列的头部元素作为当前遍历节点,并进行记录。接下来对此节点的所有相邻节点进行搜索,将所有有效且未被访问过的节点压入队列中。

  1. # Definition for a binary tree node. 
  2. # class TreeNode: 
  3. #     def __init__(self, x): 
  4. #         self.val = x 
  5. #         self.left = None 
  6. #         self.right = None 
  7. from collections import deque 
  8.  
  9. class Solution(object): 
  10.     def levelOrder(self, root): 
  11.         res = [] 
  12.         if root is None: 
  13.             return res 
  14.         q = deque([root]) 
  15.         res.append([root.val]) 
  16.         while q: 
  17.             size = len(q) 
  18.             level = [] 
  19.             for i in range(size): 
  20.                 node = q.popleft() 
  21.                 if node.left != None: 
  22.                     q.append(node.left
  23.                     level.append(node.left.val) 
  24.                 if node.right != None: 
  25.                     q.append(node.right
  26.                     level.append(node.right.val) 
  27.             if level
  28.                 res.append(level
  29.         return res 

LeetCode 第 107题:二叉树的层次遍历II

给定一个二叉树,返回其节点值自底向上的层次遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

  1. #给定二叉树 [3,9,20,null,null,15,7],  
  2. #     3 
  3. #   / \ 
  4. #  9  20 
  5. #    /  \ 
  6. #   15   7 
  7. # 返回其自底向上的层次遍历为:  
  8. # [ 
  9. #  [15,7], 
  10. #  [9,20], 
  11. #  [3] 
  12. #] 
  13. # Related Topics 树 广度优先搜索 

和LeetCode 第 102题:二叉树的层次遍历完全一样,就是最后的结果改为return res[::-1]

  1. class Solution: 
  2.     def levelOrderBottom(self, root: TreeNode) -> List[List[int]]: 
  3.         res = [] 
  4.         if root is None: 
  5.             return res 
  6.         q = deque([root]) 
  7.         res.append([root.val]) 
  8.         while q: 
  9.             size = len(q) 
  10.             level = [] 
  11.             for i in range(size): 
  12.                 node = q.popleft() 
  13.                 if node.left != None: 
  14.                     q.append(node.left
  15.                     level.append(node.left.val) 
  16.                 if node.right != None: 
  17.                     q.append(node.right
  18.                     level.append(node.right.val) 
  19.             if level
  20.                 res.append(level
  21.         return res[::-1] 

LeetCode 第 104题:二叉树的最大深度

给定一个二叉树,找出其最大深度。

  1. # 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。  
  2. # 说明: 叶子节点是指没有子节点的节点。  
  3. # 示例:  
  4. #给定二叉树 [3,9,20,null,null,15,7],  
  5. #     3 
  6. #   / \ 
  7. #  9  20 
  8. #    /  \ 
  9. #   15   7  
  10. # 返回它的最大深度 3 。  
  11. # Related Topics 树 深度优先搜索 

看到该题目,首先想到的是使用递归来实现,递归的基本条件是访问到根节点(左右子树为空);递归条件是访问左子树或右子树;中间处理逻辑是将子树深度+1,即为最终深度。

  1. # class TreeNode: 
  2. #     def __init__(self, x): 
  3. #         self.val = x 
  4. #         self.left = None 
  5. #         self.right = None 
  6.  
  7. class Solution: 
  8.  # 简化的递归 
  9.  def maxDepth(self, root: TreeNode) -> int
  10.         if not root: 
  11.             return 0 
  12.         return max(self.maxDepth(root.left), self.maxDepth(root.right))+1 
  13.  def maxDepth(self, root: TreeNode) -> int:   
  14.   if not root: return 0  
  15.   # 分别得到左右子树的最大深度 
  16.   left = self.maxDepth(root.left)     
  17.   right = self.maxDepth(root.right)     
  18.   return max(leftright) +1 

LeetCode 第 110题:平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

  1. # 本题中,一棵高度平衡二叉树定义为:  
  2. # 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。  
  3. # 示例 1:  
  4. # 给定二叉树 [3,9,20,null,null,15,7]  
  5. #     3 
  6. #   / \ 
  7. #  9  20 
  8. #    /  \ 
  9. #   15   7  
  10. # 返回 true 。  
  11. #示例 2:  
  12. # 给定二叉树 [1,2,2,3,3,null,null,4,4]  
  13. #        1 
  14. #      / \ 
  15. #     2   2 
  16. #    / \ 
  17. #   3   3 
  18. #  / \ 
  19. # 4   4 
  20. # 返回 false 。  
  21. # Related Topics 树 深度优先搜索 

定义一个获取当前节点高度的方法, 可以参考上面:求二叉树的最大深度

左右两个子树的高度差的绝对值超过1,则为false

如果当前节点的左右子树满足高度差的绝对值不超过1,则需要继续判断其左右子树分别是否是平衡二叉树。

对于每个节点,左子树和右子树都是平衡树,并且得到左子树和右子树的高度,只要高度差小于1,则为true。

  1. # Definition for a binary tree node. 
  2. # class TreeNode(object): 
  3. #     def __init__(self, x): 
  4. #         self.val = x 
  5. #         self.left = None 
  6. #         self.right = None 
  7.  
  8. class Solution: 
  9.     def isBalanced(self, root: TreeNode) -> bool: 
  10.         if not root: return True 
  11.         return abs(self.depth(root.left) - self.depth(root.right)) <= 1 and \ 
  12.             self.isBalanced(root.leftand self.isBalanced(root.right
  13.  
  14.     def depth(self, root): 
  15.         if not root: return 0 
  16.         return max(self.depth(root.left), self.depth(root.right)) +  

但是时间复杂度却是,可以采用DFS(深度优先搜索)

  • 对二叉树做深度优先遍历DFS,递归过程中:
  • 终止条件:当DFS越过叶子节点时,返回高度0;
  • 返回值:从底至顶,返回以每个节点root为根节点的子树最大高度(左右子树中最大的高度值加1 max(left,right) + 1);
  • 当我们发现有一例 左/右子树高度差 > 1 的情况时,代表此树不是平衡树,返回-1;
  • 当发现不是平衡树时,后面的高度计算都没有意义了,因此一路返回-1,避免后续多余计算。

最差情况是对树做一遍完整DFS,时间复杂度为 O(N)。

  1. class Solution: 
  2.     def isBalanced(self, root: TreeNode) -> bool: 
  3.         return self.depth(root) != -1 
  4.  
  5.     def depth(self, root): 
  6.         if not root: return 0 
  7.         left = self.depth(root.left
  8.         if left == -1: return -1 
  9.         right = self.depth(root.right
  10.         if right == -1: return -1 
  11.         return max(leftright) + 1 if abs(left - right) < 2 else -1 

本文已收录 GitHub https://github.com/MaoliRUNsen/runsenlearnpy100更多的文章

 

责任编辑:姜华 来源: Python之王
相关推荐

2021-09-15 07:56:32

二叉树层次遍历

2020-04-27 07:05:58

二叉树左子树右子树

2009-08-11 13:29:57

C#二叉树遍历

2022-10-26 23:58:02

二叉树数组算法

2021-04-20 08:37:14

数据结构二叉树

2023-05-08 15:57:16

二叉树数据结构

2021-09-15 07:40:50

二叉树数据结构算法

2021-04-19 07:47:42

数据结构二叉树Tree

2021-07-13 11:32:41

二叉树数据结构算法

2024-01-23 12:54:00

C++编程语言代码

2021-04-28 20:12:27

数据结构创建

2021-08-27 11:36:44

二叉树回溯节点

2021-09-29 10:19:00

算法平衡二叉树

2013-07-15 16:35:55

二叉树迭代器

2021-03-17 08:19:22

二叉树LeetCode

2020-09-23 18:25:40

算法二叉树多叉树

2021-10-12 09:25:11

二叉树树形结构

2018-03-15 08:31:57

二叉树存储结构

2021-03-22 08:23:29

LeetCode二叉树节点

2021-05-06 17:46:30

二叉树数据结构
点赞
收藏

51CTO技术栈公众号