lintcode-不同的二叉查找树

问题

题目:[不同的二叉查找树]

思路

这个题还是不错的,从找规律入手。本质是分治法,发现重复子问题。然后DP优化。整体的思路还是很清晰的。
主要参考了这篇链接[n个不同节点构成多少不同的二叉搜索树],讲的很清楚。
当N=1时,毫无疑问,只有一种形态。不放记f(1)为N个节点时的二叉树形态。
当N=2时,固定一个根节点,那么剩下的一个节点,要么在左枝,此时右枝为空;要么在右枝,此时左枝为空。所以f(2) = f(1)f(0) + f(0)f(1).
当N=3时,还是固定根节点。那么,左右枝可能的节点数为一下几种情况。
left = 2, right = 0;
left = 1, right = 1;
left = 0, right = 2;
那么他们相应的分支形态个数为:
f(2)*f(0);
f(1)f(1);
f(0)f(2);
所以,N=3时有f(3) = f(2)f(0) + f(1)f(1) + f(0)f(2);

综上,f(N) = f(N-1)f(0) + f(N-2)f(1) + … f(0)f(N-1)
这题是DP的一道好题啊。

状态定义:F[i]代表节点数为i时的分支形态数目;
初始化:F[0]=F[1] = 1;
转台转移:f(N) = f(N-1)f(0) + f(N-2)f(1) + … f(0)f(N-1)
结果:F[N]

这个题本质是分治的思路,利用节点数对情况进行划分,很巧妙。
多说一句,这个题的公式是catalan数。(http://blog.csdn.net/hackbuteer1/article/details/7450250).

百度百科也给了定义:

令h(0)=1,h(1)=1,catalan数满足如下递推关系式 :
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + … + h(n-1)*h(0) (n>=2)
解析解为:
h(n)=C(2n,n)/(n+1) (n=0,1,2,…)
h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,…)

怎么证参考这个链接[ Catalan数——卡特兰数]

其实上面这个题我觉得不算Catalans数的应用,他们两只是公式一样。
真正比较好的理解还是入栈出栈的合法次序问题,这是个好问题。

代码

class Solution {
public:
    /**
     * @paramn n: An integer
     * @return: An integer
     */
    int numTrees(int n) {
        // write your code here
        return catalan(n);
    }
private:
    int catalan(int n){
        vector<int> dp(n+1, 0);
        dp[0] = dp[1] = 1;
        for(int i = 2; i <= n; ++i){
            for(int j = 0; j < i; ++j){
                dp[i] += dp[j]*dp[i-1-j];
            }
        }
        return dp[n];
    }
};

下面这段代码不行,因为到N=10的时候就不行了。因为20!太大了。
所以,如果让我写catalan数的计算代码用定义的形式实现。

    long long fact(int n){
        if(n<0) return -1;
        else if(!n) return 1;
        else{
            long long ans = 1;
            for(int i = 2; i <= n; ++i){
                ans *= i;                
            }
            return ans;
        }
    }
    int cnk(int n, int k){
        return (int)(1.0/fact(k)/fact(n-k)*fact(n));
    }
    int catalan1(int n){
        return cnk(2*n, n)/(n+1);      
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值