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

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

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

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

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

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

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

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

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

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

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

后序遍历

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

python 复制代码
# 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

前序遍历

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

python 复制代码
# 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遍历所有孩子节点(其实就是上面分别判断左节点和右节点的推广)。

python 复制代码
"""
# 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)

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

依然使用后序遍历

递归法

python 复制代码
# 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

精简递归

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

python 复制代码
            # 左
            left_height = self.minDepth(root.left)
            # 右
            right_height = self.minDepth(root.right)

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

递归(后序遍历)

python 复制代码
# 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

利用完全二叉树递归

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

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

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

python 复制代码
# 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天完结🎉

相关推荐
热爱编程的小刘13 小时前
Lesson05&6 --- C&C++内存管理&模板初阶
开发语言·c++
52Hz11813 小时前
力扣230.二叉搜索树中第k小的元素、199.二叉树的右视图、114.二叉树展开为链表
python·算法·leetcode
喵手13 小时前
Python爬虫实战:网页截图归档完全指南 - 构建生产级页面存证与历史回溯系统!
爬虫·python·爬虫实战·零基础python爬虫教学·网页截图归档·历史回溯·生产级方案
张3蜂13 小时前
Python 四大 Web 框架对比解析:FastAPI、Django、Flask 与 Tornado
前端·python·fastapi
qq_124987075313 小时前
基于Java Web的城市花园小区维修管理系统的设计与实现(源码+论文+部署+安装)
java·开发语言·前端·spring boot·spring·毕业设计·计算机毕业设计
2601_9483745713 小时前
商用电子秤怎么选
大数据·python
Volunteer Technology13 小时前
Sentinel的限流算法
java·python·算法
froginwe1114 小时前
Python 条件语句
开发语言
七夜zippoe14 小时前
Python统计分析实战:从描述统计到假设检验的完整指南
开发语言·python·统计分析·置信区间·概率分布