leetcode:不同的二叉搜索树(动态规划)

https://leetcode-cn.com/problems/unique-binary-search-trees/

思路:我们可以计算以每个节点作为根节点的搜索树的数量然后求和。令f(i)表示以i为根的二叉搜索树的个数即有:Sum = f(1) + f(2) + f(3) + f(4) + ... + f(n);

但是我们知道了根节点后,下面的怎么求呢?

因为这是一颗搜索二叉树,左子树上的节点小于根节点,右子树上的节点大于根节点。假设根节点是i,那么它的左子树就有i-1个节点,右子树有n-i个节点。接着我们可以按照同样的方式递归构建左子树和右子树。所以以i为根节点的搜索树f(i),有左子树都种类数 * 右子树的种类个节点。

递归:

class Solution {
    public static int numTrees(int n) {
        if(n==0 || n==1) return 1;
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            int left = numTrees(i-1);//左子树的种类数
            int right = numTrees(n-i);//右子树的种类数
            sum+=left*right;
        }
        return sum;
    }
}

效率很低,有很多的重复计算,比如 i-1 = n-i, numTrees(i-1)和numTrees(n-i)算出的结果是一样的,但还是要计算两次。

动态规划:

在上述构建的过程中,由于根的值不同,因此我们能保证每棵二叉搜索树是唯一的。由此可见,原问题可以分解成规模较小的两个子问题,且子问题的解可以复用。因此,我们可以想到使用动态规划来求解本题。

我们可以构造两个函数:sum(i)和f(i,n)

sum(n):表示长度为n的能构成的不同二叉搜索树的个数;

f(i,n):表示以i为根节点,长度为n的不同二叉搜索树的个数;

sum(n)是我们需要的,可以通过f函数求和得到sum

已知:f(i,n) = sum(i-1) * sum(n-i);

sum(n) = \sum_{i=1}^{n}( sum(i-1) * sum(n-i) )

class Solution {
    public static int numTrees(int n) {
        int[] sum = new int[n+1];
        sum[0] = 1;sum[1] = 1;

        //i表示长度,j表示根节点
        for (int i = 2; i <=n ; i++) {
            for (int j = 1; j <= i; j++) {
                sum[i] += sum[j-1] * sum[i-j];
            }
        }
        return  sum[n];
    }
}

太难了~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值