LeetCode 95. Unique Binary Search Trees II
@(LeetCode)[LeetCode | Algorithm]
Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1 … n.
Input: 3
Output:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
Explanation:
The above output corresponds to the 5 unique BST's shown below:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
Solution #1 DP
Time:
O(Catalan(n))
O
(
C
a
t
a
l
a
n
(
n
)
)
Space:
O(Catalan(n))
O
(
C
a
t
a
l
a
n
(
n
)
)
1到n ([1, n]
) 组成的BST可以由1到n中间的任意数字作为根节点。假设根节点是k
,那么左侧是所有[1, k-1]
的BST集合,右侧是所有[k+1, n]
的BST集合。这里就可以利用DP来实现。
首先想到的就是dp[i][j]
表示所有[i, j]
BST的集合。实际上这个是可以被优化成dp[i]
的,其中,dp[i]
表示[1, i]
BST的集合。因为任意[i, j]
全都可以转化为[1, m] + offset
的形式。
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
if(n == 0)
return vector<TreeNode *>();
vector<vector<TreeNode *> > dp(n + 1, vector<TreeNode *>());
dp[0].push_back(NULL);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
int left = j - 1, right = j + 1;
for(auto left_node : dp[left]){
for(auto right_node : dp[i-j]){
TreeNode *root = new TreeNode(j);
root->left = left_node;
root->right = offset_tree(right_node, j);
dp[i].push_back(root);
}
}
}
}
return dp[n];
}
TreeNode * offset_tree(TreeNode *root, int offset) {
if(root == NULL)
return NULL;
TreeNode *new_root = new TreeNode(root->val + offset);
new_root->left = offset_tree(root->left, offset);
new_root->right = offset_tree(root->right, offset);
return new_root;
}
};
Solution 2: Divided and Conquer
在这里我使用了memo
来优化计算时间,避免重复的计算。
如上图所示,利用memo
可以避免[6, 10]
的重复计算。
typedef pair<int, int> PII;
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
if(n == 0)
return vector<TreeNode *>();
return generate_trees(1, n);
}
vector<TreeNode *> generate_trees(int start, int end) {
if(start > end)
return vector<TreeNode *>(1, NULL);
if(memo.find( PII(start, end) ) != memo.end())
return memo[PII(start, end)];
vector<TreeNode *> ret;
for(int i = start; i <= end; i++){
vector<TreeNode *> left_trees = generate_trees(start, i - 1);
vector<TreeNode *> right_trees = generate_trees(i + 1, end);
for(auto left_child : left_trees){
for(auto right_child : right_trees){
TreeNode *root = new TreeNode(i);
root->left = left_child;
root->right = right_child;
ret.push_back(root);
}
}
}
memo[PII(start, end)] = ret;
return ret;
}
private:
map<PII, vector<TreeNode *> > memo;
};