代码随想录27期|Python|Day16|二叉树|104.二叉树的最大深度|111.二叉树的最小深度|222.完全二叉树的节点个数

 二叉树专题,重点掌握后续的递归和中间节点的处理。

104. 二叉树的最大深度 - 力扣(LeetCode)

本题在前一章已经解决了层序遍历的解法,现在来聊一下递归法。

首先需要明确两个概念:深度和高度。(注意,起始位置的值都是1)

        深度:从root开始,到当前位置所在节点的层数;

        高度:从底层叶子节点开始,到当前所在节点的层数。

再来说一下选择什么顺序来遍历。

        前序:从root出发,直接找的是深度;

        后序:从叶子节点出发,返回给root节点高度。

也就是说,不管选择哪一种,中间节点都是单独处理的

后序遍历

按照递归的书写三部曲,可以写出后序遍历的方法。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # 后序遍历(Version 1)
        # step1 确定返回值类型:TreeNode
        # step2 确定终止条件:当前节点是空
        if not root:
            return 0
        else:
        # step3 单层处理:按照“左右中”的顺序,先遍历左节点高度,再遍历右节点高度,汇总到中间节点取较大值,再加1(因为当前中间节点也算作一层)
            left_height = self.maxDepth(root.left)
            right_height = self.maxDepth(root.right)
        return max(left_height, right_height) + 1

        # 精简递归(Version 2)
        return 0 if not root else max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

前序遍历

要麻烦很多,还涉及到回溯算法,十分甚至九分的不推荐

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # 递归(前序遍历)
        res = 0
        if not root:
            return 0
        self.getdepth(root, 1)
        return res

    def getdepth(self, node, depth):
        res = max(depth, res)
        if node.left == None and node.right == None:
            return
        if node.left:
            depth += 1
            self.getdepth(node.left, depth)
            depth -= 1  # 回溯算法
        if node.right:
            depth += 1
            self.getdepth(node.right, depth)
            depth -= 1
        return

559. N 叉树的最大深度 - 力扣(LeetCode)

和上面相似的一道题,只用了递归+左右中的后序遍历。

只需要用for遍历所有孩子节点(其实就是上面分别判断左节点和右节点的推广)。

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

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        if not root:
            return 0

        max_depth = 1  # 在排除顶部节点是空的时候初始化最大值是1
        
        # 遍历所有的孩子节点
        for child in root.children:
            # 注意在每次比较的时候+ 1,表示计算上了中间节点
            max_depth = max(self.maxDepth(child) + 1, max_depth)
        
        return max_depth

 111. 二叉树的最小深度 - 力扣(LeetCode)

本题需要注意的是和上面求解最大值需要遍历到底不一样,本题需要遍历到第一个叶子节点,也就是左右子树都没有的第一个节点。

依然使用后序遍历

递归法 

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # 递归法
        if not root:
            return 0
        else:
            # 左
            left_height = self.minDepth(root.left)
            # 右
            right_height = self.minDepth(root.right)
            # 中
            if root.left and root.right == None:  # 左子树存在,右子树不存在
                return left_height + 1
            if root.right and root.left == None:  # 右子树存在左子树不存在
                return right_height + 1
        # 遇到叶子节点返回到中间节点的最小值
        return min(left_height, right_height) + 1

精简递归

把求解左右高度的简化到中间处理的返回值处。

            # 左
            left_height = self.minDepth(root.left)
            # 右
            right_height = self.minDepth(root.right)

222. 完全二叉树的节点个数 - 力扣(LeetCode)

递归(后序遍历)

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # 当作普通二叉树
        if not root:
            return 0
        # 左
        left_num = self.countNodes(root.left)
        # 右
        right_num = self.countNodes(root.right)
        # 中
        return left_num + right_num + 1

        # 精简版
        if not root:
            return 0
        return self.countNodes(root.left) + self.countNodes(root.right) + 1

利用完全二叉树递归

题干当中还特别说明了是完全二叉树,所以我们可以使用完全二叉树在左右外侧深度相等的时候是满二叉树的性质来统计。

简单概括就是:如果这一层的左子树的左深度和右子树的右深度相等,那么就可以判断现在这是满二叉树。

利用这个性质,我们就很容易可以判断满足满二叉树的条件。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # 利用完全二叉树
        if not root:
            return 0

        # 判断是满二叉树直接输出
        leftnode = root.left
        rightnode = root.right
        left_depth, right_depth = 0, 0
        while leftnode:
            leftnode = leftnode.left
            left_depth += 1
        while rightnode:
            rightnode = rightnode.right
            right_depth += 1
        if left_depth == right_depth:
            return (2 << left_depth) - 1  # 2 << 1 = 2 ^ 2
        
        # 普通二叉树正常递归输出
        return self.countNodes(root.left) + self.countNodes(root.right) + 1

第16天完结🎉

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值