python算法:leetcode二叉树相关算法题

目录

[1.226. 翻转二叉树](#1.226. 翻转二叉树)

[2.101. 对称二叉树](#2.101. 对称二叉树)

[3.104. 二叉树的最大深度](#3.104. 二叉树的最大深度)

[4.111. 二叉树的最小深度](#4.111. 二叉树的最小深度)

[5.222. 完全二叉树的节点个](#5.222. 完全二叉树的节点个)


1.226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

复制代码
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

复制代码
输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

复制代码
输入:root = []
输出:[]

解题思路:

将翻转整棵树的逻辑拆解为翻转左右子树,再交换当前节点的左右子树。属于后序遍历(先处理子树再处理当前节点。

递归步骤:

1.确定传入参数和函数返回值,传入根节点,返回深度

2.确定终止条件,当前节点为None时返回

3.通过后序遍历递归翻转左右子树,再交换当前节点的左右子树

代码:

python 复制代码
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
        # 递归翻转左右子树
        self.invertTree(root.left)
        self.invertTree(root.right)
        # 交换当前节点的左右子树
        root.left, root.right = root.right, root.left
        return root

后序遍历的方法是先遍历到叶子节点在进行交换,那么前序遍历呢?反过来就可以了

python 复制代码
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
        # 前序位置交换左右子树
        root.left, root.right = root.right, root.left
        # 递归处理子树
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root

2.101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

复制代码
输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:

复制代码
输入:root = [1,2,2,null,3,null,3]
输出:false

算法思路:仔细观察不难发现,二叉树需要对称其实和我们上面一个的翻转二叉树是一样的,只不过是在代码的写法上面不一样,这里是要返回一个bool值,而且这里不是将左右对应节点交换,而是比较它们值是否相等。只要懂上面那个题,这个题就很简单了

要比较左右子树是否相等,需要满足:

1.左右子树的根节点值相等

2.左子树的左子树与右子树的右子树相等

3.左子树的右子树与右子树的左子树相等

使用递归解题:

1.参数为:传入根节点

2.返回值为:这棵树是否是对称

3.递归比较:左子树的左 vs 右子树的右,左子树的右 vs 右子树的左

python 复制代码
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True
        return self.check(root.left, root.right)
    
    def check(self, left: TreeNode, right: TreeNode) -> bool:
        # 终止条件
        if not left and not right:
            return True
        if not left or not right:
            return False
        if left.val != right.val:
            return False
        # 递归比较:左的左右 vs 右的右左
        return self.check(left.left, right.right) and self.check(left.right, right.left)

3.104. 二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

示例 1:

复制代码
输入:root = [3,9,20,null,null,15,7]
输出:3

示例 2:

复制代码
输入:root = [1,null,2]
输出:2

算法思路:最大深度就是根节点到最远距离的叶子节点之间的距离。如果我们使用递归方法来求解,单层递归思路就是:从根节点到左右节点的过程中,从求根节点的最大深度变成求左右节点的最大深度+1。然后将左右节点当作根节点再次递归。

那到叶子节点的时候呢?因为我们的递归思路是根节点的最大深度变成求左右节点的最大深度+1,因为叶子节点没有左右子树了下面为None,不存在节点,也就是没有深度了,所以这里应该返回0,也就是递归返回条件。

代码:

python 复制代码
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        left_depth = self.maxDepth(root.left)
        right_depth = self.maxDepth(root.right)
        return max(left_depth, right_depth) + 1

对递归不太熟悉的同学可能看见这个返回值会懵!其实我们假设已经递归到叶子节点了就很容易看懂了,当left_depth和right_depth都到达底部的时候因为我们的递归终止条件返回的是0,那么我们的这一层的返回值是:max(0,0)+1=1;下一层递归的时候因为上一层返回的是1,也就是right_depth=1,那么这一层的返回就是max(0,1)+1=2;如此向上回退直到递归完成。

4.111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

**说明:**叶子节点是指没有子节点的节点。

示例 1:

复制代码
输入:root = [3,9,20,null,null,15,7]
输出:2

示例 2:

复制代码
输入:root = [2,null,3,null,4,null,5,null,6]
输出:5

乍一看和上面那个题差不多,上面那个题的返回值中是+1,那么这个题呢?其实也是+1,因为我们这个加一的操作和最大最小没有关系,+1的操作是用来求深度的,那么我们控制它输出的是最大还是最小就可以了,把max换成min就可以了

但是这个题有一个坑,比如根节点下面只有左子树或者右子树的情况下,题目说的是根节点到叶子节点,而叶子节点的定义是没有左右子节点,如果我们对这种情况取最小的化一定是None的那个最小,但是它有另外一个节点,它不是叶子节点,所以我们要将这种情况单独考判断下

python 复制代码
class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        left = self.minDepth(root.left)
        right = self.minDepth(root.right)
        # 处理单侧子树为空的情况
        if not root.left:
            return right + 1
        if not root.right:
            return left + 1
        return min(left, right) + 1

5.222. 完全二叉树的节点个

给你一棵完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(从第 0 层开始),则该层包含 1~ 2h 个节点。

示例 1:

复制代码
输入:root = [1,2,3,4,5,6]
输出:6

示例 2:

复制代码
输入:root = []
输出:0

示例 3:

复制代码
输入:root = [1]
输出:1

这个题如果是用遍历方法的化很简单,不管是前中后序还是层序都可以解决,但是时间复杂度是o(n)。那有没有另外一种方法来降低时间复杂度呢

若当前子树是完美二叉树​(左右深度相等),则节点数为 2深度−1,无需递归。否则,递归计算左右子树的节点数并加 1。

步骤

  1. 计算左子树的最左路径深度(左深度)。
  2. 计算右子树的最右路径深度(右深度)。
  3. 若左右深度相等 → 完美二叉树 → 公式计算。
  4. 否则 → 递归左右子树 + 1。
python 复制代码
class Solution:
    def countNodes(self, root: TreeNode) -> int:
        if not root:
            return 0
        left_depth = self._get_depth(root.left, is_left=True)
        right_depth = self._get_depth(root.right, is_left=False)
        if left_depth == right_depth:
            return (1 << left_depth) - 1  # 2^depth -1
        return 1 + self.countNodes(root.left) + self.countNodes(root.right)
    
    def _get_depth(self, node: TreeNode, is_left: bool) -> int:
        depth = 0
        while node:
            depth += 1
            node = node.left if is_left else node.right
        return depth
相关推荐
Fantasydg3 小时前
DAY 31 leetcode 142--链表.环形链表
算法·leetcode·链表
basketball6163 小时前
C++ STL常用算法之常用排序算法
c++·算法·排序算法
moz与京3 小时前
[附C++,JS,Python题解] Leetcode 面试150题(10)——轮转数组
c++·python·leetcode
qystca3 小时前
蓝桥云客 岛屿个数
算法·dfs·bfs
什码情况4 小时前
回文时间 - 携程机试真题题解
数据结构·python·算法·华为od·机试
Alfadi联盟 萧瑶4 小时前
Python-Django入手
开发语言·python·django
lwewan5 小时前
26考研——栈、队列和数组_数组和特殊矩阵(3)
数据结构·笔记·考研·算法
拾零吖6 小时前
枚举算法-day2
数据结构·算法·leetcode
已经成为了代码的形状6 小时前
关于交换并查集内元素的一些题的做法
数据结构·算法
漠北尘-Gavin6 小时前
【Python3.12.9安装llama-cpp-python遇到编译报错问题解决】
python·llama