第一道
题目名称:96. Unique Binary Search Trees
题目难度:Medium
题目描述:Given n, how many structurally unique BST’s (binary search trees) that store values 1…n?
For example,
Given n = 3, there are a total of 5 unique BST’s.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
题目分析:
题目要求是,给定一个数n,这个数代表一个序列1…n,给出中序遍历后的结果是1…n的树的数量。(中序遍历这里其实题目中没有明确说出来,不过博主从给出的例子中推测本题的遍历指的是中序遍历,事实上也的确如此)
这是一道可以用动态规划解决的题目。解决问题的思路如下:
这些所有的树由1到n分别作为根的树构成。
假设当前是i为根,则i-1
在左子树中,i+1
在右子树中。然后再递归地算出这些子树的个数,子树的个数就是一个subproblem。
设result[n]
表示中序遍历结果为1...n
的序列的树的数量。
引入一个中间变量F(i,n)
表示以i为根的中序遍历结果为1...n
的序列的树的数量。
则
result[n] = F(1,n) + F(2,n) + F(3,n) + ... + F(n,n)
且有result[0] = result[1] = 1
F(i,n)
的值是其可能的左子树的个数和可能的右子树的数量的乘积。即:
F(i,n) = result[i-1] * result[n-i]
举个例子F(3,7) = result[2] * result[4],即[1,2,3,4,5,6,7]被拆分成[1,2]、[4,5,6,7],即求[1,2]、[4,5,6,7]构成的树的所有情况的数量。虽然[4,5,6,7]和[1,2,3,4]构成的树肯定是不同的,但是其构成的树的总量是一样的,本题只要求求数量,故可以看成是相等的。
于是我们有:
result(n) = result(0) * result(n-1) + result(1) * result(n-2) + … + result(n-1) * result(0)
于是最后的代码为:
class Solution {
public:
int numTrees(int n) {
int result[n+1];
memset(result, 0, sizeof(result));
result[0] = result[1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
result[i] += result[j - 1] * result[i - j];
}
}
return result[n];
}
};
第二道
题目名称:95. Unique Binary Search Trees II
题目难度:Medium
题目描述:Given an integer 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
题目分析:
本题跟上一题有点类似,区别只是本题要求我们将所有的树都构造出来。
根据上一题的思路,所有的情况均是由从1到n分别作为根的树构成。假设当前的根节点为i,则1到i-1是其左子树,i+1到n是其右子树。这样分别递归下去即可。
需要注意的是,虽然有多棵树的根节点的值一样,但是并不代表它们的根一样。因此应该每一个都使用一个新的副本表示根节点。
又,每一个相同的根值可能有多棵左子树和右子树,可以将这些子树放在一个数组中,按顺序调用。注意左子树和右子树之间的关系是笛卡尔积的关系。
最后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 {
public:
vector<TreeNode*> getSub(int low, int high) {
vector<TreeNode*> sub;
if (low > high) return sub;
if (low == high) {
sub.push_back(new TreeNode(low));
return sub;
}
for (int i = low; i <= high; ++i ) {
vector<TreeNode*> subLeft = getSub(low, i-1);
vector<TreeNode*> subright = getSub(i+1, high);
if (subLeft.size() == 0) {
for (int k = 0; k < subright.size(); ++k) {
TreeNode * tempHead = new TreeNode(i);
tempHead->left = NULL;
tempHead->right = subright[k];
sub.push_back(tempHead);
}
} else if (subright.size() == 0) {
for (int k = 0; k < subLeft.size(); ++k) {
TreeNode * tempHead = new TreeNode(i);
tempHead->right = NULL;
tempHead->left = subLeft[k];
sub.push_back(tempHead);
}
} else {
for (int j = 0; j < subLeft.size(); ++j) {
for (int k = 0; k < subright.size(); ++k) {
TreeNode * tempHead = new TreeNode(i);
tempHead->left = subLeft[j];
tempHead->right = subright[k];
sub.push_back(tempHead);
}
}
}
}
return sub;
}
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> result;
if (n <= 0) return result;
if (n == 1) {
result.push_back(new TreeNode(1));
return result;
}
for (int i = 1; i <= n; ++i) {
vector<TreeNode*> subLeft = getSub(1, i-1);
vector<TreeNode*> subright = getSub(i+1, n);
if (subLeft.size() == 0) {
for (int k = 0; k < subright.size(); ++k) {
TreeNode * tempHead = new TreeNode(i);
tempHead->left = NULL;
// cout << subright[k] << endl;
tempHead->right = subright[k];
result.push_back(tempHead);
}
} else if (subright.size() == 0) {
for (int k = 0; k < subLeft.size(); ++k) {
TreeNode * tempHead = new TreeNode(i);
tempHead->right = NULL;
tempHead->left = subLeft[k];
result.push_back(tempHead);
}
} else {
for (int j = 0; j < subLeft.size(); ++j) {
for (int k = 0; k < subright.size(); ++k) {
TreeNode * tempHead = new TreeNode(i);
tempHead->left = subLeft[j];
tempHead->right = subright[k];
result.push_back(tempHead);
}
}
}
}
return result;
}
};