Description

給定一棵二元樹,判斷它是否是高度平衡的。高度平衡的二元樹定義為:每個節點的左右子樹高度差不超過 1。

Example:

Input: root = [3,9,20,null,null,15,7] Output: true

Intuition#

自底向上計算高度,一旦發現任何節點不平衡就提前回報 -1。

  • 平衡的定義是遞迴的:根平衡 + 左右子樹都平衡
  • 自頂向下會重複計算高度,自底向上只需一次遍歷

Approaches#

1: Top-Down(自頂向下)#

  • 概念: 對每個節點計算左右子樹高度,檢查差值,再遞迴檢查子樹
  • 時間複雜度: O(n^2),每個節點都要重新計算高度
  • 空間複雜度: O(n)
class Solution {
    fun isBalanced(root: TreeNode?): Boolean {
        if (root == null) return true
        val diff = Math.abs(height(root.left) - height(root.right))
        return diff <= 1 && isBalanced(root.left) && isBalanced(root.right)
    }

    private fun height(node: TreeNode?): Int {
        if (node == null) return 0
        return 1 + maxOf(height(node.left), height(node.right))
    }
}

⭐ 2: Bottom-Up(自底向上)#

  • 概念: 遞迴計算高度時,若發現不平衡就回傳 -1 作為標記,提前結束
  • 時間複雜度: O(n)
  • 空間複雜度: O(h)
class Solution {
    fun isBalanced(root: TreeNode?): Boolean {
        return checkHeight(root) != -1
    }

    private fun checkHeight(node: TreeNode?): Int {
        if (node == null) return 0
        val left = checkHeight(node.left)
        if (left == -1) return -1
        val right = checkHeight(node.right)
        if (right == -1) return -1
        if (Math.abs(left - right) > 1) return -1
        return 1 + maxOf(left, right)
    }
}

🔑 Takeaways#

  • Pattern: 自底向上(Bottom-Up)比自頂向下(Top-Down)更高效,避免重複計算
  • 關鍵技巧: 用特殊回傳值(如 -1)作為「不合法」的標記,可以在遞迴中提前終止