# 1382. Balance a Binary Search Tree
**練習日期:** 2026-02-09
**難度:** Medium
**類型:** Tree、Binary Search Tree、Divide and Conquer、Depth-First Search
## 📘 題目敘述
給你一棵二元搜尋樹(Binary Search Tree, BST)的根節點 `root`,請回傳一棵**高度平衡**(balanced)的二元搜尋樹,且它包含**完全相同的節點值**。
如果有多種答案,回傳任意一種都可以。
一棵 BST 被稱為平衡的,如果每個節點的左右子樹深度差的絕對值都不超過 `1`。
### 條件限制
* 節點數量在範圍 `[1, 10^4]`
* `1 <= Node.val <= 10^5`
## 🧠 解題思路
我先想清楚這題想要的是什麼:
> 我不需要保留原本樹的形狀,只需要保留「所有值」,並重新組成一棵平衡 BST。
所以我把問題拆成兩段:
1. **把樹的所有節點值收集出來**
我用 DFS 走訪整棵樹,把每個節點的 `val` 放進 `nums`。
2. **用這些值重新建一棵平衡 BST**
平衡 BST 最直覺的做法就是:
把值排序後變成一個遞增陣列,接著每次選中間當根,左右兩邊遞迴建樹。
這樣每層切一半,高度就會接近平衡。
這份 code 的邏輯就是:
`search(root)` 收集所有值 → `sort(nums)` 變成遞增序列 → `build(l, r)` 用中點建立平衡樹。
### 所有變數
* `nums`:存整棵樹所有節點值的陣列(收集完後會排序)
* `l`:`build(l, r)` 的左邊界
* `r`:`build(l, r)` 的右邊界
* `m`:目前區間 `[l, r]` 的中點索引
* `root`(build 裡的區域變數):新建立的子樹根節點指標
## 🪜 主要流程步驟
### 1. 先用 DFS 把所有節點值收集到 `nums`
我寫了一個 `search(root)`:
只要 `root` 不為空,就把 `root->val` 放進 `nums`,然後遞迴走左子樹、右子樹。
這步的目的很單純:先把「有哪些值」全部拿到。
### 2. 把 `nums` 排序,得到遞增序列
因為要重建 BST,排序後的陣列會變成 BST 的中序結果(遞增)。
有了遞增陣列,我就可以用「選中間當根」的方法保證平衡。
### 3. 用 `build(l, r)` 從排序後的陣列建平衡 BST
`build(l, r)` 代表:用 `nums[l...r]` 這段數值來建一棵平衡 BST。
* 如果 `l > r`,代表這段沒有元素,回傳 `nullptr`
* 否則取中點 `m = (l + r) / 2`
* 建立根節點 `new TreeNode(nums[m])`
* 左子樹用 `build(l, m - 1)` 建
* 右子樹用 `build(m + 1, r)` 建
這樣每一層都把資料切成左右兩半,所以整棵樹的高度會被壓到接近平衡。
### 4. 回傳新樹根
在 `balanceBST(root)` 裡,收集 + 排序後,直接回傳 `build(0, nums.size() - 1)` 的結果,這就是平衡後的 BST。
## 💻 程式碼實作
```cpp
/**
* Definition for a binary tree node.
* 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:
vector<int> nums;
void search(TreeNode* root) {
if (root) {
nums.push_back(root->val);
search(root->left);
search(root->right);
}
return;
}
TreeNode* build(int l, int r) {
if (l > r) {
return nullptr;
}
int m = (l + r) / 2;
TreeNode* root = new TreeNode(nums[m]);
root->left = build(l, m - 1);
root->right = build(m + 1, r);
return root;
}
TreeNode* balanceBST(TreeNode* root) {
search(root);
sort(nums.begin(), nums.end());
return build(0, nums.size() - 1);
}
};
```
## 🔗 題目連結
https://leetcode.com/problems/balance-a-binary-search-tree/description/