题目描述

✅ 剑指 Offer 55 - II. 平衡二叉树

image-20261001230752582

image-20260928195059126

image-20260928195059128

题意分析

判断二叉树是否高度平衡:每一个节点的左右子树高度差都不超过 1。条件要对整棵树的所有节点成立,因此只比较根的左右高度不够;空树也属于平衡树。

解法:后序剪枝

核心思路

[!blue]

判断当前子树,需要先知道左右子树是否平衡以及各自的高度,适合用后序遍历自底向上汇总。让 height(node) 同时传递这两种信息:子树平衡时返回真实高度,不平衡时返回 -1。合法高度从 0 开始,不会与失败标记混淆。

空节点返回 0。先递归求左子树,得到 -1 就直接返回,不必继续检查右边;右子树失败时也一样。两边都平衡后,若高度差超过 1,当前子树仍然不平衡;否则返回 max(left, right) + 1。

一处失衡就足以使整棵树不平衡,-1 会沿父节点一直传回根。每个被访问的节点只计算一次高度,避免在每个节点重新遍历左右子树。

解题步骤

  1. 当前节点为空,返回高度 0。
  2. 递归取得左子树高度 left,若为 -1,立即返回 -1。
  3. 递归取得右子树高度 right,若为 -1,立即返回 -1。
  4. 两个高度相差超过 1 时返回 -1,否则返回较大高度加 1。
  5. 根节点的返回值不是 -1,就说明整棵树平衡。

代码实现

class Solution {
    public boolean isBalanced(TreeNode root) {
        return height(root) != -1;
    }

    // 平衡子树返回非负高度,任一失衡则返回负一。
    private int height(TreeNode node) {
        if (node == null) {
            return 0;
        }

        int left = height(node.left);

        // 负一表示子树已失衡,直接上传,不再把它当高度。
        if (left == -1) {
            return -1;
        }

        int right = height(node.right);

        if (right == -1) {
            return -1;
        }

        // 两侧各自平衡后,还需检查当前节点的高度差。
        if (Math.abs(left - right) > 1) {
            return -1;
        }

        return Math.max(left, right) + 1;
    }
}
func isBalanced(root *TreeNode) bool {
    return height(root) != -1
}

// 平衡子树返回非负高度,任一失衡则返回负一。
func height(node *TreeNode) int {
    if node == nil {
        return 0
    }

    left := height(node.Left)
    // 负一表示子树已失衡,直接上传,不再把它当高度。
    if left == -1 {
        return -1
    }

    right := height(node.Right)
    if right == -1 {
        return -1
    }

    // 两侧各自平衡后,还需检查当前节点的高度差。
    if left-right > 1 || right-left > 1 {
        return -1
    }

    if left > right {
        return left + 1
    }
    return right + 1
}

复杂度分析

  • 时间复杂度:$O(n)$,其中 n 为节点数;每个节点至多访问一次,提前发现失衡时可能更早结束。
  • 空间复杂度:$O(h)$,递归栈深度等于树高 h;最坏链状树为 $O(n)$。

关键点总结

[!green]

  • 负一与所有合法高度区分开,必须在求最大值之前检查。
  • 空树返回零,因此属于平衡树。
  • 左右子树各自平衡、当前节点高度差合格,三个条件缺一不可。

易错点总结

[!yellow]

  • 只判断根节点会遗漏内部失衡。
  • 把失败记为零,会与空子树高度混淆。
  • 只比较 left - right > 1 会漏掉右边更高的情况,必须检查高度差的绝对值。

相似题目

题目 难度 关联与区别
104. 二叉树的最大深度 简单 后序求高度是基础,本题同时把子树是否失衡的信息向上传递。
543. 二叉树的直径 简单 同样用左右子树高度在当前节点计算附加结果,原题求最长路径长度。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/51794850
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!