题目链接:Unique Binary Search Trees II
Given n, generate all structurally unique BST‘s (binary search trees) that store values 1...n.
For example,
Given n = 3, your program should return all 5 unique BST‘s shown below.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
OJ‘s Binary Tree Serialization:
The serialization of a binary tree follows a level order traversal, where ‘#‘ signifies a path terminator where no node exists below.
Here‘s an example: 1 / \ 2 3 / 4 \ 5
The above binary tree is serialized as "{1,2,3,#,#,4,#,#,5}".
这道题的要求是用1...n生成结构不同的二叉搜索树(BST)。
二叉搜索树,顾名思义,它是一个二叉树,即每个节点下面最多有2个子节点。同时为了便于搜索的特性,二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:
- 若其左子树不空,则左子树上所有结点的值均小于根结点的值;
- 若其右子树不空,则右子树上所有结点的值均大于根结点的值;
- 其左、右子树也分别为二叉搜索树。
这是对Unique Binary Search Trees的扩展,不是返回数目,而是需要生成所有情况的二叉搜索树。
1. 递归分治
要生成1...n的所有结构不同的二叉搜索树,可依次令根节点为1...n。假设当前根节点为i,则其左子树为1...i-1的所有结构不同的二叉搜索树,右子树为i+1...n的所有结构不同的二叉搜索树。因此,左右子树分别转化为两个子问题了,可以选择递归处理该子问题即可。
由于不同二叉搜索树的数量是卡特兰数,因此这道题的时间复杂度是卡特兰数。
时间复杂度:O(???)
空间复杂度:O(???)
1 class Solution
2 {
3 public:
4 vector<TreeNode *> generateTrees(int n)
5 {
6 return generateTrees(1, n);
7 }
8 private:
9 vector<TreeNode *> generateTrees(int l, int r)
10 {
11 vector<TreeNode *> v;
12
13 if(l > r)
14 v.push_back(NULL);
15
16 for(int i = l; i <= r; ++ i)
17 {
18 vector<TreeNode *> vl = generateTrees(l, i - 1);
19 vector<TreeNode *> vr = generateTrees(i + 1, r);
20 for(int j = 0; j < vl.size(); ++ j)
21 for(int k = 0; k < vr.size(); ++ k)
22 {
23 TreeNode *t = new TreeNode(i);
24 t -> left = vl[j];
25 t -> right = vr[k];
26 v.push_back(t);
27 }
28 }
29
30 return v;
31 }
32 };
2. 动态规划
由于问题可以转化为子问题进行求解,因此可以选择记录已求解的子问题。记录存储的时候,为了降低空间复杂度,不采用dp[i][j]来存储i...j的所有情况,而采用dp[len]存储长度为len的所有情况,即1...len的所有情况。这样,在需要i+1...r的子问题解的情况时,需要对1...r-i的节点数值加上偏移i即可,即对dp[r-i]的所有情况加上偏移i。TreeNode * clone(TreeNode *root, int offset)函数的功能就是对root树中节点的数值进行加上偏移offset处理。
时间复杂度:O(???)
空间复杂度:O(???)
1 class Solution
2 {
3 public:
4 vector<TreeNode *> generateTrees(int n)
5 {
6 // dp[i]存储1...i的二叉搜索树
7 vector<vector<TreeNode *> > dp(n + 1);
8 dp[0].push_back(NULL);
9
10 for(int len = 1; len <= n; ++ len)
11 for(int i = 1; i <= len; ++ i)
12 for(int l = 0; l < dp[i - 1].size(); ++ l)
13 for(int r = 0; r < dp[len - i].size(); ++ r)
14 {
15 TreeNode *p = new TreeNode(i);
16 p -> left = dp[i - 1][l];
17 p -> right = clone(dp[len - i][r], i);
18 dp[len].push_back(p);
19 }
20
21 return dp[n];
22 }
23 private:
24 TreeNode * clone(TreeNode *root, int offset)
25 {
26 if(root == NULL)
27 return NULL;
28
29 TreeNode *p = new TreeNode(root -> val + offset);
30 p -> left = clone(root -> left, offset);
31 p -> right = clone(root -> right, offset);
32 return p;
33 }
34 };