Leet Code -- Unique BST

对于数字n(大于1)。从1到n有多少种binary search tree(BST序列)?
当n=3时,BST序列为:


   1         3     3    2     1
     \         /     /      / \      \
     3      2    1    1  3     2
     /       /       \                  \
   2      1         2                3
共5种。


分析:


N=1时,BST 序列为
 1
 /   \
      null  null
1种


N=2时,BST 序列为
1        2
 \        /

  2    1


2种


N=3时。BST序列为
   1         3     3      2      1
     \         /     /       / \       \
     3     2     1      1   3      2
    /       /        \                    \
   2     1         2                    3
5种


N=4时。BST序列为
1                                                        4                      2                                          3
 \             +                                        /                 +    / \                             +          / \
 2,3,4(5种)                              1,2,3(5种)   (1种)1  3,4 (2种)              (2种)1 ,2    4(1种)
共  5+5+1*2+2*1 = 14种


N=5时。BST序列为

   1                                              2                                                  3                                                     4                                     

     \                                             / \                                                 /  \                                                  /  \                                    

  2,3,4,5(14种)             (1种)1   3,4,5(5种)           (2种)1,2  4,5(2种)               (5种)1,2,3  5(1种)               


        5

      /

1,2,3,4(14种)

因此,count(5) = 14 + 1*5 + 2*2 + 5*1 + 14 = 42种


看上去存在一种递推关系。考虑DP来解。
找规律。求递推公式:
设S(n)为n相应的情况数,S(0)=1 ,则。
S(1) = 1
S(2) = 2
S(3) = S(0) * S(2) + S(1) * S(1) + S(2) * S(0) = 5
S(4) = S(0) * S(3) + S(1) * S(2) + S(2) * S(1) + S(3) * S(0) = 14


不难发现,
S(N) = Sum{S(K-1) * S(N-K) ,当中K∈[1,N]}


得到了递推公式,下一步就是写代码了:





public class Solution {
    public int NumTrees(int n) {
        if(n <= 0) {
		return 1;
	}
	
	// - dp array
	var dp = new int[n+1];
	dp[0] = 1;
	dp[1] = 1;
	
	for(var j = 2; j <= n; j++){
		// i: 1.. j
		// dp[j] = sum (dp[i-1] * dp[j-i])
		var s = 0;
		for(var i = 1; i <= j; i++){
			s += dp[i-1] * dp[j-i];
		}
		
		dp[j] = s;
	}
	
	return dp[n];
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值