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
依然是递归编程。一般在用到递归技巧时候都可以使用动态DP(动态规划)进行优化。
下面两种解决方法分别用到了递归和DP。
方法一、
假设1....n中的第i个值为根节点,则1....i-1构成左子树,i+1构成有右子树。以i为根节点的树的个数为(左子树的个数)*(右子树的个数)。
class Solution {
public:
int numTrees(int n) {
return numTrees(1,n);
}
int numTrees(int start,int end)
{
int total=0;
if(start>=end)
{
return 1;
}
for(int i=start;i<=end;i++)
{
total+=numTrees(start,i-1)*numTrees(i+1,end);
}
return total;
}
};
方法二(DP优化)、
class Solution {
public:
/*
* 依次枚举出所有节点作为根节点,根据BST的性质,根节点左边的节点组成的左子树就成为了一个子问题
* ,右子树同样;所以这是一个DP问题。
* 按照DP问题的一般解法,使用顺序数组numSeqs来存储中间结果,自底向上
* 求出所有中间值来即可
* 需要注意的是,
* 1、左右子树如果都不为空,那么tempSum应该用乘法原则;
* 2、如果有一颗子树不为空,那么tempSum应该用加法;
* 3、如果根节点即是叶子节点,那么只有1棵树,tempSum加1即可。
* */
int numTrees(int n) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
//用来存储所有的n对应的numTrees值
vector<int> numSeqs(n+1, 0);
numSeqs[0]=0, numSeqs[1]=1;
if(n < 2) return numSeqs[n];
int tempSum = 0;
int leftNodes, rightNodes;
//从2到n自底向上依次计算到numSeqs(n)
for(int i = 2; i <= n; i++)
{
tempSum = 0;
//对于任意的numSeq(i),从1到n依次枚举出所有BST顶点的情况
for(int rootPos = 1; rootPos <= i; rootPos++)
{
//leftNodes是以rootPos为根节点的树的左子树的个数,rightNodes是右子树的个数
leftNodes = rootPos - 1;
rightNodes = i - rootPos;
if(leftNodes && rightNodes)
tempSum +=numSeqs[rootPos-1] * numSeqs[i-rootPos];
else if(leftNodes || rightNodes)
tempSum += numSeqs[rootPos-1] + numSeqs[i-rootPos];
else
tempSum += 1;
}
numSeqs[i] = tempSum;
}
return numSeqs[n];
}
};