No.70 - LeetCode96 - n个节点的不同结构二叉搜索树的个数

先给出一种自己的做法:时间O(N^3),可以AC

直觉是n节点二叉搜索树的结构是通过n-1节点扩展出来的,且有一定规律。

花了15分钟,貌似找到了这个规律:

二叉搜索树结构数

因为新插入的点一定是最大的,所以可以通过插缝的方式插入新节点n,但是有些是不满足二叉搜索树的排序关系,去掉后就是如图的逻辑关系。

class Solution {
public:
    int numTrees(int n) {
        int dp[n+1][n+1];
        memset(dp,0,sizeof(dp));
        dp[1][1] = 1;
        for(int i=2;i<=n;i++){
            for(int j=1;j<=i;j++){
                for(int k=j-1;k<i;k++){
                    dp[i][j] += dp[i-1][k];
                }
            }
        }
        int ans = 0;
        for(int i=1;i<=n;i++) ans+=dp[n][i];
        return ans;
    }
};

进阶版,O(N^2)的做法:

时间压缩一下,类似于快速幂的思路,
只用n节点信息可以扩展出n+1节点的信息,但是把1~n节点的信息都利用就可以加快计算。
一个n+1节点的二叉搜索树可以划分为,左边0个,根1个(值为1),右边n个;左边1个,根1个(值为2),右边n-1个;…以此类推。

把每个值都轮番作为根节点,由于二叉搜索树的特性,左子树上节点集合一定比根小,右子树节点集合一定比根大,所以相当于递归处理。

class Solution {
public:
    int numTrees(int n) {
        int dp[n+1];
        memset(dp,0,sizeof(dp));
        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-j-1];
            }
        }
        return dp[n];
    }
};

究极版,O(N)的做法:

根据进阶版递归公式
f(0) = f(1) = 1
f(n) = f(0)*f(n-1) + f(1)*f(n-2) + … + f(n-1)*f(0)

这个东西叫做Catalan数:

快速计算公式:

f(n) = C(2n,n) / (n+1)

class Solution {
public:
    int numTrees(int n) {
        long long ans = 1;
        for(int i=1;i<=n;i++) ans = (n+i)*ans/i;
        return ans/(n+1);
    }
};

注:ans一定要用long long,否则会溢出,这里只能先乘n+i再除i,否则可能出现整数除法错误。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值