给出n个数字,能够构建出多少个不同的bst。
这道题可以用动态规划来做。那么动态规划重要的是找出状态,以及状态转移方程。
我们来考虑一下状态以及转移,我们可以列举出数组里面每一个数字i来当bst的root,然后根据bst的性质我们知道root左边的都是比他小的,右边都是比他大的。显然,左子树是用[1,i-1],右子树是用[i+1,n]构建的,那么我们会发现如果对于每一个i我们都这样的去构建这个问题就会转移到左右子树的构建上去。于是我们就发现了状态的转移。但是这个转移如何用数学的方法表示出来呢。
设G(n)为n个数字构建出的bst总数,F(i,n)为n个数字,i为root的时候可以构建的bst的数目。
那么我们仿佛找到了一个关系:
G(n) = F(1,n)+F(2,n)+...+F(n,n)
所以这个F关系式怎么转化呢?
假设我们有[1,2,3,4,5,6]6个数,我选2为root,那么2的左边有[1],右边有[3,4,5,6],所以[1]能构建bst的数目是G(1),而[3,4,5,6]能构建bst数目的是G(4),为什么呢?因为我构建bst主要的是看增序数组的元素个数跟元素具体是什么,是不是从1开始的并没有什么关系.
于是:
F[2,6] = G(1)G(4);
F[i,n] = G(i-1)G(n-i);
所以这个G(n)就可以算了:
G(n) = G(0)G(n-1)+G(1)G(n-2)+...+G(n-1)*G(0)
G(0)=G(1) =1
于是这个状态转移方程我们也得出来了。
int dp[n+1];
dp[0]=dp[1]=1;
for(int i=2;i<=n;++i)
{
dp[i]=0;
for(int j=1;i<=i;++j)
dp[i] += dp[j-1]+dp[i-j];
}
return dp[n];
基本上按这翻译的:https://discuss.leetcode.com/topic/8398/dp-solution-in-6-lines-with-explanation-f-i-n-g-i-1-g-n-i/17