其他分享
首页 > 其他分享> > 【树】力扣104:二叉树的最大深度

【树】力扣104:二叉树的最大深度

作者:互联网

输入是一个二叉树,输出是一个整数,表示该树的最大深度。

二叉树的深度为根节点到最远叶子节点(没有子节点的节点)的最长路径上的节点数。

示例:

给定二叉树 [3,9,20,null,null,15,7]
image
返回它的最大深度 3 。


相关知识

来源:https://leetcode.cn/problems/maximum-depth-of-binary-tree/solution/acm-xuan-shou-tu-jie-leetcode-er-cha-shu-ckf4/

二叉树的层次 或称 二叉树的深度 是从根节点算起,根节点是第一层,依次往下类推。

二叉树的高度是从叶子节点算起,叶子节点高度是 1,依次往上类推。可以看成是高楼,从下往上看,也就是自底向上看。

二叉树的深度和高度正好相反,且 二叉树的最大高度 = 最大深度。

求深度的方法

  1. 前序遍历:用自顶向下的方法遍历二叉树,就是从根节点递归到叶子节点,计算这一条路径上的深度,并更新维护最大深度
    image

  2. 后序遍历:用自底向上的方法遍历二叉树,就是从叶子节点开始,一层一层的向上,最终汇集在根节点。实质上求的是高度
    image

  3. 层次遍历:用自左向右的方法遍历二叉树,就是从根节点开始,一层一层的遍历二叉树。求的是二叉树的层次,二叉树的最大层次就是其最大深度
    image


深度优先搜索

如果知道了左子树和右子树的最大深度 left 和 right,那么该二叉树的最大深度即为

\[max(left, right) + 1 \]

而左子树和右子树的最大深度又可以用同样的方式进行计算。因此可以用「深度优先搜索」的方法来计算二叉树的最大深度。

采用自底向上的后序遍历方法:

  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/=
  1. 终止条件:若结点为空,退出递归,返回 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:

image

# 初始化队列和层次
queue = [root]
depth = 0

2. 当队列不为空,出队列,将所有的子节点入队列

depth = 1:
image

image

depth = 2:
image
image

depth = 3:
image

# 当队列不为空
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