算法通关村第八关-二叉树的深度和高度问题

最大深度问题

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

LeetCode104
https://leetcode.cn/problems/maximum-depth-of-binary-tree/

思路分析

方法1:递归(后序遍历)

最大深度 depth = 1+max(leftDepth, rightDepth),可以用递归实现;递归结束条件 node == null 返回0;先拿到左右子树的结果再计算总的结果,可以看做是后序遍历的扩展问题

int leftDepth = getDepth(node.left); //左
int rightDepth = getDepth(node.right); //右
int depth = 1+max(leftDepth, rightDepth); //中

方法2:层序遍历

如果确定了树最大有几层,也就知道最大深度了。套用层序遍历的代码。

代码实现

方法1:递归(后序遍历)

# 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:
        # 方法1:递归(后序遍历)
        if not root:
            return 0
        left_depth = self.maxDepth(root.left)
        right_depth = self.maxDepth(root.right)
        return 1+max(left_depth, right_depth)

方法2:层序遍历

# 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:
        # 方法2:层序遍历
        if not root:
            return 0
        queue = collections.deque([root])
        depth = 0
        while queue:
            # 当前层的节点数
            n = len(queue)
            for i in range(n):
                node = queue.pop()
                if node.left:
                    queue.appendleft(node.left)
                if node.right:
                    queue.appendleft(node.right)
            depth += 1
        return depth

判断平衡树

LeetCode110
https://leetcode.cn/problems/balanced-binary-tree/

高度平衡二叉树:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1

高度和深度的定义
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数

注:这里的定义有不同的标准,LeetCode以节点数为准,根节点的深度为1,叶子节点的高度为1

思路分析

方法1:获取所有节点再判断

获取节点的高度

  • 如果节点为空,高度为0
  • 如果节点非空,节点高度为 左右子树中最大高度加1 max(left, right)+1

判断是否是高度平衡二叉树

  • 如果节点为空,是
  • 如果节点不为空,判断所有节点的左右子树高度差绝对值是否都不超过1

方法2:一边获取高度,一边判断

获取节点的高度

  • 如果节点为空,高度为0
  • 如果节点非空,节点高度为 左右子树中最大高度加1 max(left, right)+1
  • 若节点左子树/右子树为非高度平衡二叉树,则其高度返回 -1 (标志位),只要子树中有非高度平衡二叉树,其父/祖节点高度就为 -1 (标志位),只要子树中有非高度平衡二叉树,该二叉树就不是高度平衡二叉树

判断是否是高度平衡二叉树

  • 如果节点为空,是
  • 如果节点不为空,判断所有节点的左右子树高度差绝对值是否都不超过1

代码实现

方法1:

# 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 isBalanced(self, root: Optional[TreeNode]) -> bool:
        # 获取节点高度
        def height(node):
            if not node:
                return 0
            left_height = height(node.left)
            right_height = height(node.right)
            return max(left_height, right_height)+1

        if not root:
            return True
        # 注意:这里是每个节点都要满足条件
        return abs(height(root.left)-height(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)

方法2:

# 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 isBalanced(self, root: Optional[TreeNode]) -> bool:
        def height(node):
            if not node:
                return 0
            left_height = height(node.left)
            right_height = height(node.right)
            if left_height == -1 or right_height == -1 or abs(left_height-right_height) > 1:
                return -1
            else:
                return max(left_height, right_height)+1
        
        return height(root) >= 0

最小深度问题

LeetCode111
https://leetcode.cn/problems/minimum-depth-of-binary-tree/

思路分析

说明:叶子节点是指没有子节点的节点。前两个题都涉及最大深度,那将max改成min能不能解决问题呢?不行,注意下图
在这里插入图片描述

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。最小深度的一层必须要有叶子节点,因此不能直接用

方法1:递归

核心:

  • 如果左子树为空,右子树非空,最小深度为右子树最小深度+1
  • 如果左子树非空,右子树为空,最小深度为左子树最小深度+1
  • 如果左子树和右子树都非空,最小深度为左右子树最小深度最小值+1

方法2:层次遍历
遍历时,第一次遇到叶子就直接返回其所在的层次即可

代码实现

方法1:递归

# 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 minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        elif not root.left and not root.right:
            return 1
        elif root.left and root.right:
            return min(self.minDepth(root.left), self.minDepth(root.right)) + 1
        elif root.left:
            return self.minDepth(root.left) + 1
        elif root.right:
            return self.minDepth(root.right) + 1
# 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 minDepth(self, root: Optional[TreeNode]) -> int:
        # 代码改进优化
        if not root:
            return 0
        if not root.left and not root.right:
            return 1
        
        min_depth = 10**9
        if root.left:
            min_depth = min(self.minDepth(root.left), min_depth)
        if root.right:
            min_depth = min(self.minDepth(root.right), min_depth)

        return min_depth + 1

方法2:层次遍历

# 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 minDepth(self, root: Optional[TreeNode]) -> int:
        # 方法2:层次遍历
        if not root:
            return 0
        queue = collections.deque([root])
        level = 1
        while queue:
            for i in range(len(queue)):
                node = queue.pop()
                if not node.left and not node.right:
                    return level
                if node.left:
                    queue.appendleft(node.left)
                if node.right:
                    queue.appendleft(node.right)
            level += 1
# 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 minDepth(self, root: Optional[TreeNode]) -> int:
        # 方法2:层次遍历
        if not root:
            return 0
        queue = collections.deque([(root, 1)])
        while queue:
            node, depth = queue.pop()
            if not node.left and not node.right:
                return depth
            if node.left:
                queue.appendleft((node.left, depth+1))
            if node.right:
                queue.appendleft((node.right, depth+1))

N叉数的最大深度

LeetCode559
https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/

思路分析

将二叉树换成了N叉数,不同点就在于N叉数的节点比较多,使用List存,最大的区别是处理子树时加了个处理List的for循环

可用递归和层次遍历解决

代码实现

方法1:递归

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        # 方法1:递归
        if not root:
            return 0
        if not root.children:
            return 1
        return max([ self.maxDepth(node) for node in root.children]) + 1
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        # 方法1:递归(代码简化)
        return max([ self.maxDepth(node) for node in root.children], default=0) + 1 if root else 0

方法2:层次遍历

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        # 方法2:层次遍历
        if not root:
            return 0
        queue = collections.deque([root])
        level = 0
        while queue:
            for i in range(len(queue)):
                node = queue.pop()
                for j in node.children:
                    queue.appendleft(j)
            level += 1
        return level
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值