【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)。
相关推荐
努力长头发的程序猿42 分钟前
Unity2D当中的A*寻路算法
算法·unity·c#
Raink老师2 小时前
用100道题拿下你的算法面试(矩阵篇-2):求转置矩阵
算法·面试·矩阵
算法鑫探8 小时前
闰年判断:C语言实战解析
c语言·数据结构·算法·新人首发
WBluuue8 小时前
数据结构与算法:康托展开、约瑟夫环、完美洗牌
c++·算法
木子墨5168 小时前
LeetCode 热题 100 精讲 | 并查集篇:最长连续序列 · 岛屿数量 · 省份数量 · 冗余连接 · 等式方程的可满足性
数据结构·c++·算法·leetcode
王老师青少年编程9 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:均分纸牌
c++·算法·编程·贪心·csp·信奥赛·均分纸牌
EQUINOX19 小时前
2026年码蹄杯 本科院校赛道&青少年挑战赛道提高组初赛(省赛)第一场,个人题解
算法
萝卜小白9 小时前
算法实习Day04-MinerU2.5-pro
人工智能·算法·机器学习
Liangwei Lin10 小时前
洛谷 P3133 [USACO16JAN] Radio Contact G
数据结构·算法
weixin_5134499610 小时前
PCA、SVD 、 ICP 、kd-tree算法的简单整理总结
c++·人工智能·学习·算法·机器人