ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-07-12 11:03:57  阅读:242  来源: 互联网

标签:node queue 力扣 depth 二叉树 深度 节点 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有