【LeetCode 每日一题】110. 平衡二叉树——(解法二)自底向上 + 剪枝

Problem: 110. 平衡二叉树

文章目录

  • [1. 整体思路](#1. 整体思路)
  • [2. 完整代码](#2. 完整代码)
  • [3. 时空复杂度](#3. 时空复杂度)
      • [时间复杂度: O ( N ) O(N) O(N)](#时间复杂度: O ( N ) O(N) O(N))
      • [空间复杂度: O ( N ) O(N) O(N)](#空间复杂度: O ( N ) O(N) O(N))

1. 整体思路

核心问题

判断二叉树是否平衡。

算法逻辑

同样采用自底向上 的递归。

区别在于:

  1. 左子树优先检查
    • 先递归计算左子树的高度 l
    • 关键剪枝 :如果左子树返回 -1(说明左边已经不平衡了),那么整棵树肯定不平衡。此时不需要再递归计算右子树 ,直接向上返回 -1
  2. 右子树检查
    • 只有当左子树平衡(l != -1)时,才去递归计算右子树的高度 r
    • 如果右子树返回 -1,同样直接向上返回 -1
  3. 高度差检查
    • 如果左右子树都平衡,最后检查当前节点的左右高度差 Math.abs(l - r)
    • 如果超过 1,返回 -1
    • 否则返回当前高度 max(l, r) + 1

这种写法在遇到不平衡树时(特别是左子树就不平衡的情况),能够显著减少递归调用的次数。


2. 完整代码

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        // 调用 dfs,如果返回 -1 说明树不平衡
        return dfs(root) != -1;
    }

    private int dfs(TreeNode node) {
        // 递归终止条件:空节点高度为 0
        if (node == null) {
            return 0;
        }

        // 1. 先递归左子树
        int l = dfs(node.left);
        
        // 剪枝优化:如果左子树已经不平衡,直接返回 -1
        // 这一步避免了后续对右子树的递归调用 dfs(node.right)
        if (l == -1) {
            return -1;
        }

        // 2. 只有左子树平衡,才递归右子树
        int r = dfs(node.right);
        
        // 检查右子树是否不平衡,或者当前节点左右高度差是否 > 1
        // 如果任意条件满足,标记为不平衡 (-1)
        if (r == -1 || Math.abs(l - r) > 1) {
            return -1;
        }

        // 3. 左右子树都平衡且高度差 <= 1,返回当前节点高度
        return Math.max(l, r) + 1;
    }
}

3. 时空复杂度

假设二叉树节点数为 N N N。

时间复杂度: O ( N ) O(N) O(N)

  • 计算依据
    • 最坏情况下(整棵树是平衡的,或者不平衡发生在最右下角),我们需要遍历所有节点,每个节点访问一次。
    • 最好情况下(根节点的左子树直接就不平衡),我们只需要访问左子树的部分节点,甚至只访问常数个节点(如果树极度不平衡且偏左)。
    • 总体上仍是线性复杂度 O ( N ) O(N) O(N),但在平均情况下比无剪枝版本更快。
  • 结论 : O ( N ) O(N) O(N)。

空间复杂度: O ( N ) O(N) O(N)

  • 计算依据
    • 空间消耗主要来自递归栈。
    • 最坏情况(退化为链表): O ( N ) O(N) O(N)。
    • 平均/最好情况(平衡树): O ( log ⁡ N ) O(\log N) O(logN)。
  • 结论 : O ( N ) O(N) O(N)。
相关推荐
寻寻觅觅☆10 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子11 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS12 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar12312 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS12 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗13 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
忙什么果13 小时前
上位机、下位机、FPGA、算法放在哪层合适?
算法·fpga开发
董董灿是个攻城狮13 小时前
AI 视觉连载4:YUV 的图像表示
算法
ArturiaZ14 小时前
【day24】
c++·算法·图论
大江东去浪淘尽千古风流人物15 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam