LeetCode 打卡 Day 42 —— 不同的二叉搜索树

1、题目

2、题解

跟昨天一样又是树,还是一棵新树,来简单了解下二叉搜索树,它是满足如下条件的二叉树

  • 左子树所有节点小于根节点
  • 右子树所有节点大于根节点
  • 左右子树均为二叉搜索树

脑海中首先的想法是从1到n遍历整数n,每个遍历到的数字均可能作为数的根节点,由此依次遍历,递归无疑是最适合的方法

  • 递归函数的参数:整数start,end,表示树的节点范围
  • 递归出口:树仅有一个节点或没有节点 start>=end
  • 递归内容:确定当前树的节点,以及当前节点对应树的个数为 “左子树个数*右子树个数”

最后实现代码如下:

func numTrees(n int) int {
    var searchTree func(start, end int) int
    searchTree = func(start, end int) int{
        res:=0
        if start>=end{
            return 1
        }
        for i:=start; i<=end; i++ {
            res+=searchTree(start, i-1)*searchTree(i+1, end)
            // fmt.Println("r:",i,"  l:",l,"  r:",r)
        }
        return res
    }
    return searchTree(1, n)
}

以上代码虽然通过了测试,但是在提交中却显示时间超出了限制(n<=19)

 莫得办法,只能想办法降低时间复杂度了,因为递归通常能够通过 循环+增加空间消耗 代替,而递归较为费时,尝试将递归改遍历循环,那就需要构建存储空间,保存节点数为i (0<=i<=n) 时的子树个数,这样一想,不就是动态规划吗😂,难道算法也是个圈吗,实现代码如下

func numTrees(n int) int {
    dp := make([]int, n+1)
    dp[0],dp[1] = 1, 1
    for i:=2; i<=n; i++{
        for j:=1; j<=i; j++{
            dp[i]+=dp[j-1]*dp[i-j]
        }
    }
    return dp[n]
}

提交成功,提交结果如下

 看题解之后,发现还有别的思路,搜索树的个数满足卡塔兰数Cn

C0=1,Cn+1 = 2Cn(2n+1)/(n+2)

实现代码如下

func numTrees(n int) int {
    s := 1
    for i:=0; i<n; i++ {
        // fmt.Println(s)
        s=2*s*(2*i+1)/(i+2)
    }
    return s
}

提交结果如下,内存使用降低了一点,但时间上由于n最大仅为19,所以时间效率提升并不明显

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值