【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)。
相关推荐
Niuguangshuo5 小时前
论文解读:CTC,端到端序列识别的开山之作
算法·语音识别
讳疾忌医丶5 小时前
深度拆解 RocksDB 内核:基于 C++17 的 FIFO 调度状态机与温度阶梯自愈设计
java·c++·算法·架构
高亦真6 小时前
今天是学习嵌入式的第37天
linux·学习·算法
罗西的思考7 小时前
[Agent Memory / 强化学习] MemPO源码学习笔记 --- (2)--- 训练
人工智能·算法·机器学习
深圳市方中禾科技9 小时前
FZH1625 LCD 驱动芯片深度评测与实战指南
算法·led
我不会起名字3229 小时前
一天一道算法题(34):回溯法的经典例题(子集)
java·数据结构·python·算法·golang·深度优先·力扣
huang57914711 小时前
哈希算法的抗碰撞机制与安全性增强策略4
算法
林浩杨_11 小时前
SIGIR 2026|南京大学:Video-GAR:“通过生成 Query 来验证视频语义理解”的生成增强范式
论文阅读·人工智能·算法
Elsa️74612 小时前
算法一周刷题总结
c++·算法
小小程序猴112 小时前
深圳乘路资讯AI培训怎么样?课程靠谱吗?——一套课程可信度评估模型与实证分析
人工智能·算法