跳转至

Balanced Binary Tree (平衡二元樹) 🟢 Easy

📌 LeetCode #110題目連結 | NeetCode 解說

1. 🧐 Problem Dissection (釐清問題)

題目給一個 Binary Tree,判斷它是否是 高度平衡 (Height-Balanced) 的。 Height-Balanced: 一個二元樹中,每個節點 的左右子樹的高度差絕對值不超過 1。

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

      3
     / \
    9  20
      /  \
     15   7
    

  • Output: true (9 height 1, 20 height 2. Diff 1. Max balance OK.)

  • Input: root = [1,2,2,3,3,null,null,4,4]

           1
          / \
         2   2
        / \
       3   3
      / \
     4   4
    

  • Output: false (Node 1 left height 4, right height 1. Diff > 1)

  • Constraints:
    • \(0 <= nodes <= 5000\)
    • \(-10000 <= Node.val <= 10000\)

2. 🐢 Brute Force Approach (暴力解)

對於每個節點 root,計算 height(root->left)height(root->right)。 如果 abs(left - right) > 1,回傳 false。 否則遞迴檢查 isBalanced(root->left)isBalanced(root->right)

  • Time: \(O(N^2)\)。因為對於上層節點,計算 height 會重複訪問下層所有節點。
  • Result: 效率不佳。

3. 💡 The "Aha!" Moment (優化)

這也是一個 Bottom-up DFS。 我們可以修改 height() 函數,讓它不僅回傳高度,還能在發現 不平衡 時回傳一個特殊信號 (例如 -1)。

Modified DFS:

  • 如果左子樹回傳 -1 (不平衡),直接回傳 -1。
  • 如果右子樹回傳 -1 (不平衡),直接回傳 -1。
  • 如果 abs(left - right) > 1,回傳 -1。
  • 否則回傳 1 + max(left, right)

最後在 main 函數檢查 dfs(root) != -1

🎬 Visualization (演算法視覺化)

全螢幕開啟視覺化


4. 💻 Implementation (程式碼)

Approach: Recursive DFS (Bottom-up with -1 flag)

#include <algorithm>
#include <cmath>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    bool isBalanced(TreeNode* root) {
        return dfsHeight(root) != -1;
    }

private:
    // Returns height of tree if balanced, -1 if unbalanced
    int dfsHeight(TreeNode* root) {
        if (!root) return 0;

        int leftHeight = dfsHeight(root->left);
        if (leftHeight == -1) return -1; // Propagate failure

        int rightHeight = dfsHeight(root->right);
        if (rightHeight == -1) return -1; // Propagate failure

        if (abs(leftHeight - rightHeight) > 1) {
            return -1; // Current node unbalanced
        }

        return 1 + max(leftHeight, rightHeight);
    }
};

Python Reference

class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:

        def dfs(root):
            if not root:
                return [True, 0]

            left, right = dfs(root.left), dfs(root.right)

            balanced = (left[0] and right[0] and
                        abs(left[1] - right[1]) <= 1)

            return [balanced, 1 + max(left[1], right[1])]

        return dfs(root)[0]

5. 📝 Detailed Code Comments (詳細註解)

class Solution {
public:
    bool isBalanced(TreeNode* root) {
        // 如果 dfsHeight 回傳 -1,代表發現不平衡
        return checkHeight(root) != -1;
    }

private:
    // Helper function:
    // 如果平衡,回傳高度 (>= 0)
    // 如果不平衡,回傳 -1
    int checkHeight(TreeNode* node) {
        if (node == nullptr) return 0;

        // Check Left Subtree
        int leftH = checkHeight(node->left);
        if (leftH == -1) return -1; // 提早結束

        // Check Right Subtree
        int rightH = checkHeight(node->right);
        if (rightH == -1) return -1; // 提早結束

        // Check Current Node
        if (abs(leftH - rightH) > 1) {
            return -1; // 當前節點不平衡
        }

        // 回傳高度
        return 1 + max(leftH, rightH);
    }
};

6. 📊 Rigorous Complexity Analysis (複雜度分析)

  • Time Complexity: \(O(n)\)
    • Bottom-up 每個節點只計算一次。
  • Space Complexity: \(O(h)\)
    • Recursive stack depth.

7. 💼 Interview Tips (面試技巧)

🎯 Follow-up 問題

面試官可能會問的延伸問題:

  • 如何從不平衡樹轉為平衡?
  • AVL Tree?

🚩 常見錯誤 (Red Flags)

避免這些會讓面試官扣分的錯誤:

  • ⚠️ 每個節點重複計算高度
  • ⚠️ 沒有 early termination

✨ 加分項 (Bonus Points)

這些會讓你脫穎而出:

  • 💎 O(n) 一趟遍歷
  • 💎 返回 -1 表示不平衡的技巧

站內相關