二叉树理论、力扣94.二叉树的中序遍历、104.二叉树的最大深度、226.反转二叉树、101.对称二叉树

0.理论基础

参考:

二叉树理论基础篇 | 代码随想录

分类:

1、满二叉树:

如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。

2、完全二叉树:

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

3、二叉搜索树:

有数值且有序

  • 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  • 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  • 它的左、右子树也分别为二叉排序树

4、平衡二叉搜索树:

又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

遍历方式:

1、深度优先遍历:

先往深走,遇到叶子节点再往回走。

前中后序指中间节点的遍历顺序

  • 前序遍历------中左右(递归法,迭代法)
  • 中序遍历------左中右(递归法,迭代法)
  • 后序遍历------左右中(递归法,迭代法)

2、广度优先遍历:

逐层遍历

94.二叉树的中序遍历

一、递归

三部曲:

1、确定递归函数的参数和返回值:传入节点

2、确定终止条件:遍历节点为空直接返回

3、确定单层循环逻辑:中序遍历为左中右,按顺序循环,取中间节点数值

代码:

python 复制代码
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []

        def dfs(node):
            if node is None:
                return 
            dfs(node.left)  # 递归左子树
            res.append(node.val)  # 中间节点加入结果数组
            dfs(node.right)  # 递归右子树

        dfs(root)
        return res

二、迭代

思路:

用栈存储,需要时取出顶部元素。由于是中序遍历,首先迭代访问左子树,遍历到最左节点后取出栈顶元素加入结果数组,然后向栈顶元素的右子树进行遍历。

代码:

python 复制代码
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 为空的情况
        if root is None:
            return []

        # 创建一个栈,先存储节点,便于回溯
        stack = []
        res = []
        cur = root

        # 需要两个
        while cur or stack:
            # 栈非空且当前节点非空
            if cur:
                # 向左遍历并存储(按中间、左节点的顺序存的,取出就为先取左节点再取的中间)
                stack.append(cur)
                cur = cur.left
            else: # 栈非空但当前节点为空
                # 取出左边/中间的节点存入结果数组,再向右遍历
                cur = stack.pop()
                res.append(cur.val)
                cur = cur.right

        return res

104.二叉树的最大深度

一、层序遍历

参考:

讲透二叉树的层序遍历 | 广度优先搜索 | LeetCode:102.二叉树的层序遍历_哔哩哔哩_bilibili

思路:

使用队列,用一个变量记录该层元素个数,以知道后续要从队列中弹出的元素个数;遍历每一层时需要将对应元素的子节点加入到队列当中

代码:

python 复制代码
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0

        # 记录深度,创建列表
        depth = 0
        queue = collections.deque([root])

        while queue:
            depth += 1
            size = len(queue)  # 记录每一层的节点数

            # 按层来取出节点,加入下一层节点
            for _ in range(size):
                cur = queue.popleft()
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)

        return depth

二、递归

三部曲:

1、确定参数及返回值:参数为节点,返回值为高度

2、确定终止条件:遍历节点为空返回0

3、确定单层循环逻辑:一定要是后序遍历左右中,因为只有把两个子树先遍历完了才能够对左子树和右子树高度进行比较,否则无法比较

代码:

python 复制代码
class Solution:
    def getDepth(self, node):
        if not node:
            return 0
        
        leftHeight = self.getDepth(node.left)
        rightHeight = self.getDepth(node.right)
        height = 1 + max(leftHeight, rightHeight)

        return height

    def maxDepth(self, root: Optional[TreeNode]) -> int:
        return self.getDepth(root)

226.反转二叉树

思路:

先交换左右节点,然后再递归处理左子树右子树

代码:

python 复制代码
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None:
            return root

        root.left, root.right = root.right, root.left
        self.invertTree(root.left)
        self.invertTree(root.right)

        return root

复杂度分析:

  • 时间复杂度:O(n),其中 n 为二叉树的节点个数。
  • 空间复杂度:O(n)。最坏情况下,二叉树退化成一条链,递归需要 O(n) 的栈空间。

101.对称二叉树

一、递归

思路:

递归处理二叉树的外侧节点和内侧节点,分别对比对应节点是否相同;把特殊情况单列出来返回,包括:对应节点一个为空一个非空、都非空、值不相等的情况,此时可以直接返回,若两个值相等了,就可以继续递归

代码:

python 复制代码
class Solution:
    def compare(self, left, right):
        # 把左右节点的各种情况单独列出
        if left is None and right:
            return False
        elif right is None and left:
            return False
        elif right is None and left is None:
            return True
        elif left.val != right.val:
            return False

        # 分别遍历二叉树的外侧节点和内侧节点,来判断是否都相同
        outside = self.compare(left.left, right.right)
        inside = self.compare(left.right, right.left)
        isSame = outside and inside

        return isSame

    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if root is None:
            return True

        return self.compare(root.left, root.right)

复杂度分析:

  • 时间复杂度:O(n),其中 n 为二叉树的节点个数。
  • 空间复杂度:O(n)。最坏情况下,二叉树退化成一条链,递归需要 O(n) 的栈空间。

二、迭代

思路:

和层序遍历有点像,用队列来成对记录左右节点,方便对比

代码:

python 复制代码
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if root is None:
            return True

        queue = collections.deque([root.left, root.right])  # 要传入左右节点

        while queue:
            leftNode = queue.popleft()
            rightNode = queue.popleft()

            # 两节点都为空
            if not leftNode and not rightNode:
                continue

            # 两节点有一个不为空或者值不相等
            if not leftNode or not rightNode or leftNode.val != rightNode.val:
                return False
            
            # 先传入外侧两节点,再传入内测两节点,方便两两对比
            queue.append(leftNode.left)
            queue.append(rightNode.right)
            queue.append(leftNode.right)
            queue.append(rightNode.left)

        return True
相关推荐
卖个几把萌2 小时前
解决 Python 项目依赖冲突:使用 pip-tools 一键生成现代化的 requirements.txt
开发语言·python·pip
Shirley~~2 小时前
leetcode移除元素
javascript·数据结构·算法
黎雁·泠崖2 小时前
Java字符串入门:API入门+String类核心
java·开发语言·python
普贤莲花2 小时前
新生2026年1月20日---星期二(大寒)
程序人生·算法·leetcode
高洁012 小时前
产品数字孪生体与数字样机及数字化交付的应用
人工智能·深度学习·算法·数据挖掘·transformer
2501_941507942 小时前
通信基站天线设备检测与分类YOLO11-LSCD-LQE算法实现与优化
算法·分类·数据挖掘
wen__xvn2 小时前
基础数据结构第08天:栈(实战篇)
数据结构·c++·算法
玄鱼殇2 小时前
前端排序算法
算法·排序算法
哈哈不让取名字2 小时前
用Pygame开发你的第一个小游戏
jvm·数据库·python