leetcode_middle_45_96. Unique Binary Search Trees

题意:

给一个n,问能存储从1到n 的二叉排序树有多少个。

分析:

我们对前几个比较小的树,举例子画图分析。我们一定要搞清楚,为什么3个结点就是5个树,4个结点就是14个树。多画了几个树之后,很明显自然地就想到动态规划,我们能不能用不同的结点做根结点,然后左子树的值乘上右子树,任由子树变换。

这就是我们的编程思维:

对于一个树:

                                  *

                      *(left) *(right)

比如一个9个结点的,现在左子树有3个结点,右子树有5个结点,再加一个根结点,所以f(9) = f(3) * f(5)  (当第四个结点做根节点的时候),我们只需要将每个结点做根的结果求和即可。(而不需要管左右子树具体是什么情况),后面就比较简单了,不做分析。

小结:

我一直认为智力是个伪命题,只有针对某特定领域问题的一定思维模式下的思考效率。而编程就是要培养一种编程思维模式,我们不要像解数学题一样去找n与f(n)的关系,也不是出于找递推去找规律,本质算法就不是找规律,而是找解决办法,(不是找值是多少,而是找怎么求得这个值的)我们应该从一般情况出发,从动态变化出发,我们举个例子画个图,或者去想一个比较大的n,它的f(n)是怎么得出来的?左子树好复杂,右子树好复杂,但是子树的变化情况我们是已知的(动态存储,即动态规划)所以左子树的值乘上右子树的值,就是那颗树的值,再考虑遍历所有结点做根的情况即可。

得出解法的必然性:我们一定要去想子树啊,动态的想,不要去管子树具体啥样。而去想树和子树的联系。

public class Solution {
    public int numTrees(int n) {
        if(n < 3){
            return n;
        }
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        int tmp = 0;
        int j = 1;
        for(int i=3; i<=n; i++){
            j = 1;
            
            while(j <= i/2){
                tmp += 2*dp[i-j]*dp[j-1];
                j++;
            }
            if(i%2 != 0)
                tmp +=  dp[j-1]*dp[j-1];
            
            dp[i] = tmp;
            tmp = 0;
        }
        return dp[n];
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值