給出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