题目描述
给定一个n,我们可以构建多少棵二叉搜索树呢?使用值1~n填充树的节点.
举个例子,如果n=3,那么一共会存在5棵这样的树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
题目分析
这是一道非常经典的题目,很有意思.在此之前,我们有必要了解一下二叉搜索树的知识:
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
需要注意的是, 如果以 i 节点为根,那么编号小于 i 的节点只可能出现在 i 的左子树中,编号大于 i 的节点只能出现在 i 的右子树中.
对于给定的1~n节点,我们知道,每个节点都可以充当二叉搜索树的根.
如果以1号节点为根,求这种类型的二叉搜索树一共有多少棵?那么问题可以转化为,求2~n节点所能够成的二叉搜索树的棵数.
如果以2号节点为根,求这种类型的二叉搜索树一共有多少颗?问题转化成了两个子问题,第一个子问题是求以1节点所能构成的二叉搜索树的棵数,第二个子问题是求以3~n节点所能构成的二叉搜索树的棵数.然后将两者相乘,得到结果.
如果以3号节点为根,求这种类型的二叉搜索树一共有多少颗?问题转化成了两个子问题,第一个子问题是求以1,2节点所能构成的二叉搜索树的棵数,第二个子问题是求以3~n节点所能构成的二叉搜索树的棵数.然后将两者相乘,得到结果.
…
如果以n号节点为根,求这种类型的二叉搜索树一共有多少颗?那么问题可以转化为,求1~n-1节点所能够成的二叉搜索树的棵数.
然后将上面的结果加起来,就可以得到问题的解.
#include <iostream>
using namespace std;
class Solution {
public:
int numTrees(int n) {
int dp[4000];
dp[0] = 0; dp[1] = 1; dp[2] = 2; dp[3] = 5;
for (int i = 4; i <= n; i++) {
int sum = 0;
for (int j = 1; j < i - 1; j++)
sum += dp[j] * dp[i - 1 - j];
dp[i] = sum + 2 * dp[i - 1];
}
return dp[n];
}
};
int main()
{
Solution so;
cout << so.numTrees(4) << endl;
getchar();
}
题目扩展
得到这些二叉搜搜索树
直接上代码吧:
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
vector<TreeNode *> generateTrees(int begin, int end) {
vector<TreeNode *> trees;
if (begin > end) {
trees.push_back(NULL); /* 空树 */
return trees;
}
if (begin == end) {
trees.push_back(new TreeNode(begin));
return trees;
}
for (int root_idx = begin; root_idx <= end; root_idx++) {
vector<TreeNode *> ltrees = generateTrees(begin, root_idx - 1); /* 左子搜索树 */
vector<TreeNode *> rtrees = generateTrees(root_idx + 1, end); /* 右子搜索树 */
for (auto ltree : ltrees) {
for (auto rtree : rtrees) {
TreeNode *tree = new TreeNode(root_idx);
tree->left = ltree; tree->right = rtree;
trees.push_back(tree); /* 合并成新树 */
}
}
}
return trees;
}
public:
vector<TreeNode*> generateTrees(int n) {
if (n == 0) return vector<TreeNode *>();
return generateTrees(1, n);
}
};
int main()
{
Solution so;
cout << so.generateTrees(4).size() << endl;
getchar();
}