Different binary search treesy|Go主题月

1,857 阅读3分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看<活动链接>

【Java 刷题打卡 】刷题比玩游戏好多了,成就感越来越强,每天坚持刷几道题,每天锻炼30分钟,等8块腹肌,等大厂offer.

那就干吧! 这个专栏都是刷的题目都是关于动态规划的,我会由浅入深、循序渐进,刷题就是这样需要连续不断的记忆--艾宾浩斯记忆法2121112。动态规划的内容不多,但是都是每个程序员必备的

这道题很经典啦😄😄😄 \color{green}{这道题很经典啦😄 😄 😄 ~}

什么题可以选择动态规划来做?

1.计数

有多少种方式走到右下角

有多少种方法选出k个数是的和是sum

2.求最大值最小值

从左上角走到右下角路径的最大数字和

最长上升子序列长度

3.求存在性

取石子游戏,先手是否必胜

能不能选出k个数使得和是sum

leecode 96. 不同的二叉搜索树

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例:

输入: 3

输出: 5

解释:

给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

-- 首先要知道二叉搜索树是根节点大于左节点小于右节点。

动态规划四步走~~~ ❤️❤️❤️❤️

2.1. 动态规划组成部分1:确定状态

简单的说,解动态规划的时候需要开一个数组,数组的每个元素f[i]或者f[i][j]代表什么,类似数学题中x, y, z代表什么

最后一步

给定一个有序序列 1 到n,为了构建出一棵二叉搜索树,我们可以遍历每个数字 ii,将该数字作为树根,将 1 到 (i-1)序列作为左子树,将 (i+1) 到n 序列作为右子树。接着我们可以按照同样的方式递归构建左子树和右子树。

在上述构建的过程中,由于根的值不同,因此我们能保证每棵二叉搜索树是唯一的。

子问题

由此可见,原问题可以分解成规模较小的两个子问题,且子问题的解可以复用。因此,我们可以想到使用动态规划来求解本题。

2.2. 动态规划组成部分2:转移方程

假设 n 个节点存在二叉排序树的个数是 G (n),令 f(i) 为以 i 为根的二叉搜索树的个数,则

G(n) = f(1) + f(2) + f(3) + f(4) + ... + f(n)

当 i 为根节点时,其左子树节点个数为 i-1 个,右子树节点为 n-i,则 f(i) = G(i-1)*G(n-i)

想一想这里为什么是笛卡尔积呢? \color{red}{想一想这里为什么是笛卡尔积呢?~}想一想这里为什么是笛卡尔积呢?

简单的将第二个公式带入第一个公式可以得到 (卡特兰数) 公式 G(n) = G(0)G(n-1)+G(1)(n-2)+...+G(n-1)*G(0)

2.3. 动态规划组成部分3:初始条件和边界情况

当序列长度为 1(只有根)或为 0(空树)时,只有一种情况,即 G(0)=1,G(1)=1

2.4. 动态规划组成部分4:计算顺序

自顶向下

参考代码

JAVA版

    public int numTrees(int n) {
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        
        for(int i = 2; i < n + 1; i++)
            for(int j = 1; j < i + 1; j++) 
                dp[i] += dp[j-1] * dp[i-j];
        
        return dp[n];
    }

真心感谢帅逼靓女们能看到这里,如果这个文章写得还不错,觉得有点东西的话

求点赞👍 求关注❤️ 求分享👥 对8块腹肌的我来说真的 非常有用!!!

如果本篇博客有任何错误,请批评指教,不胜感激 !❤️❤️❤️❤️