这是我参与更文挑战的第22天,活动详情查看: 更文挑战
什么题可以选择动态规划来做?
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];
}
❤️❤️❤️❤️
非常感谢人才们能看到这里,如果这个文章写得还不错,觉得有点东西的话 求点赞👍 求关注❤️ 求分享👥 对帅气欧巴的我来说真的 非常有用!!!
如果本篇博客有任何错误,请批评指教,不胜感激 !