【树】力扣104:二叉树的最大深度
作者:互联网
输入是一个二叉树,输出是一个整数,表示该树的最大深度。
二叉树的深度为根节点到最远叶子节点(没有子节点的节点)的最长路径上的节点数。
示例:
给定二叉树 [3,9,20,null,null,15,7]
返回它的最大深度 3 。
相关知识
二叉树的层次 或称 二叉树的深度 是从根节点算起,根节点是第一层,依次往下类推。
二叉树的高度是从叶子节点算起,叶子节点高度是 1,依次往上类推。可以看成是高楼,从下往上看,也就是自底向上看。
二叉树的深度和高度正好相反,且 二叉树的最大高度 = 最大深度。
求深度的方法
-
前序遍历:用自顶向下的方法遍历二叉树,就是从根节点递归到叶子节点,计算这一条路径上的深度,并更新维护最大深度
-
后序遍历:用自底向上的方法遍历二叉树,就是从叶子节点开始,一层一层的向上,最终汇集在根节点。实质上求的是高度
-
层次遍历:用自左向右的方法遍历二叉树,就是从根节点开始,一层一层的遍历二叉树。求的是二叉树的层次,二叉树的最大层次就是其最大深度
深度优先搜索
如果知道了左子树和右子树的最大深度 left 和 right,那么该二叉树的最大深度即为
\[max(left, right) + 1 \]而左子树和右子树的最大深度又可以用同样的方式进行计算。因此可以用「深度优先搜索」的方法来计算二叉树的最大深度。
采用自底向上的后序遍历方法:
- 重复的子问题:递归计算出其左子树和右子树的最大深度,在 O(1) 时间内计算出当前二叉树的最大深度
# 递归计算左子树的最大深度
leftHeight = self.maxDepth(root.left)
# 递归计算右子树的最大深度
rightHeight = self.maxDepth(root.right)
# 二叉树的最大深度 = 子树的最大深度 + 1(1 是根节点)
maxHeight = max(leftHeight, rightHeight) + 1
作者:rocky0429-2
链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/solution/acm-xuan-shou-tu-jie-leetcode-er-cha-shu-ckf4/=
- 终止条件:若结点为空,退出递归,返回 0
递归
# 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 maxDepth(self, root: Optional[TreeNode]) -> int:
return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) if root else 0
时间复杂度:O(n),其中 n 为二叉树节点的个数。每个节点在递归中只被遍历一次。
空间复杂度:O(height),其中 height 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度。
非递归
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
stack = [(1, root)]
depth = 0
while stack:
curDep, node = stack.pop()
depth = max(depth, curDep)
if node.right:
stack.append((curDep + 1, node.right))
if node.left:
stack.append((curDep + 1, node.left))
return depth
广度优先搜索
也可以用「广度优先搜索」的方法来解决这道题目,但需要对其进行一些修改。此时广度优先搜索的队列里存放的是「当前层的所有节点」:每次拓展下一层的时候,不同于广度优先搜索的每次只从队列里拿出一个节点,而是将队列里的所有节点都拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是当前层的所有节点,即一层一层地进行拓展。最后用一个变量 ans 来维护拓展的次数,该二叉树的最大深度即为 ans。
这也就是从左到右的层次遍历方法:
使用队列保存每一层的所有节点,把队列里的所有节点出队列,然后把这些出去节点各自的子节点入队列。用 depth 维护每一层。
1. 初始化队列 queue 和层次 depth,将根节点入队列
depth = 0:
# 初始化队列和层次
queue = [root]
depth = 0
2. 当队列不为空,出队列,将所有的子节点入队列
depth = 1:
depth = 2:
depth = 3:
# 当队列不为空
while queue:
n = len(queue) # 当前层的节点数
# 弹出当前层的所有结点,并将所有子结点入队列
for i in range(n):
node = queue.pop(0)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
depth += 1
作者:rocky0429-2
链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/solution/acm-xuan-shou-tu-jie-leetcode-er-cha-shu-ckf4/
整体代码
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
# 空树,高度为 0
if root == None:
return 0
# 初始化队列和层次
queue = [root]
depth = 0
# 当队列不为空
while queue:
n = len(queue) # 当前层的节点数
# 弹出当前层的所有节点,并将所有子节点入队列
for i in range(n):
node = queue.pop(0)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
depth += 1
return depth # 二叉树最大层次即为二叉树最大深度
作者:rocky0429-2
链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/solution/acm-xuan-shou-tu-jie-leetcode-er-cha-shu-ckf4/
时间复杂度:O(n),其中 n 为二叉树的节点个数。与方法一同样的分析,每个节点只会被访问一次。
空间复杂度:此方法空间的消耗取决于队列存储的元素数量,其在最坏情况下会达到 O(n)。
代入模板的版本代码
与 DFS 的前序遍历不同,BFS 的层次遍历最后得到的深度一定是最大深度,不需要用 max() 判断。
DFS 结点右孩子先入栈,左孩子再入栈。而 BFS 结点左孩子先入栈,右孩子再入栈。
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
queue = [(1, root)]
while queue:
depth, node = queue.pop(0)
if node.left:
queue.append((depth + 1, node.left))
if node.right:
queue.append((depth + 1, node.right))
return depth
标签:node,queue,力扣,depth,二叉树,深度,节点,104 来源: https://www.cnblogs.com/Jojo-L/p/16469250.html