給定 n,生成所有鍵值為 1...n 的結構不同的二叉搜索樹(BST)。返回所有可能的樹根節點列表。
n = 3 時共有 5 棵不同結構的 BST:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
與「不同的二叉搜索樹 I」(只求數量,用 Catalan 數 DP)不同,本題需顯式構造每棵樹,子問題不重疊,無法用 DP 優化時間,複雜度本質上是 O(C_n)(Catalan 數級別)。
root = 1..n。1..root-1 遞歸生成所有可能。root+1..n 遞歸生成所有可能(值需 +root 偏移)。n == 0 返回 {nullptr};n == 1 返回單節點樹。base 參數傳遞值偏移,避免重複創建節點值。unordered_map)可緩存相同 (n, base) 的結果,但本題 base 不同導致緩存命中率低,通常不加也能 AC。/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
private:
// 可選:記憶化加速
// unordered_map<long long, vector<TreeNode*>> memo;
vector<TreeNode*> gen(int n, int base) {
vector<TreeNode*> res;
if (n == 0) { res.push_back(nullptr); return res; }
if (n == 1) { res.push_back(new TreeNode(base + 1)); return res; }
for (int root = 1; root <= n; ++root) {
auto leftTrees = gen(root - 1, base);
auto rightTrees = gen(n - root, base + root);
for (auto L : leftTrees) {
for (auto R : rightTrees) {
TreeNode* node = new TreeNode(base + root);
node->left = L;
node->right = R;
res.push_back(node);
}
}
}
return res;
}
public:
vector<TreeNode*> generateTrees(int n) {
if (n == 0) return {};
return gen(n, 0);
}
};
O(C_n),C_n = (2n)!/((n+1)!n!) 為第 n 個 Catalan 數。O(C_n) 存儲結果 + O(n) 遞歸棧。dp[n] = Σ dp[i-1]*dp[n-i] 即可 O(n²)。