day41 动态规划part3
day41-1 343.整数拆分
动态规划五部曲:
- 定义dp数组并明确其含义:dp[i]的含义是将i拆分,得到的数的最大乘积为dp[i]
- 递推公式:
- dp[i] = j * (i - j) i被拆分为两个数的情况
- dp[i] = j * dp[i - j] i被拆分为三个及三个以上的数的情况
- 初始化:
- dp[0] = 0
- dp[1] = 0
- dp[2] = 1
- 遍历顺序: i 从 0 到n
- 打印数组
class Solution {
public int integerBreak(int n) {
// 定义dp, dp[i] 为正整数 i 拆分后的结果的最大乘积
int[] dp = new int[n+1];
// 初始化
dp[0] = 0;// 将第二次for循环的j限定小一点就用不了这个初始化数
dp[1] = 0;// 将第二次for循环的j限定小一点就用不了这个初始化数
dp[2] = 1;
for(int i = 3; i <= n; i++){
for(int j = 1; j <= i -j; j++){
// 这里的 j 最大值为 i- j ,再大就是重复前面的情况
// 使用两次max的原因是:在i确定的时候要找到dp[i]的最大值
dp[i] = Math.max(dp[i], Math.max(j*(i - j), j*dp[i-j]));
// j * (i - j) 是单纯的把整数 i 拆分为两个数 也就是 i,i-j ,再相乘
// j * dp[i - j]是将 i 拆分成两个以及两个以上的个数,再相乘。
}
}
return dp[n];
}
}
day41-2 96.不同的二叉搜索树
推导:
n=3的情况找dp[3]可以把问题分解为头结点为1,头结点为2,头结点为3三种情况:
从而得出递推公式
所以,该题的动态规划五部曲内容为:
- 定义dp数组并明确其含义:dp[i]的含义是输入i得到互不相同的二叉搜索树的种数
- 递推公式:
dp[i] +=dp[j-1] (左子树)+ dp[i - j](右子树)
(其中的j
为头结点) —>难点:需要举例、画图、分析才能得到递推关系 - 初始化:
- dp[0] = 1 (空结点也是二叉搜索树)
- dp[1] = 1
- 遍历顺序: i 从 1 到 n 从小到大进行遍历
- 打印数组
class Solution {
public int numTrees(int n) {
// 定义dp 数组, dp[i]的含义为1到i为节点组成的二叉搜索树的个数为dp[i]。
int[] dp = new int[n + 1];
// 初始化
dp[0] = 1; // 空结点也是二叉搜索树
dp[1] = 1;
for(int i = 2; i <= n; i++){
for(int j = 1; j <= i; j++){// 二叉搜索树头结点数值
// dp[j - 1] 左子树 ;dp[i - j]右子树
// 对于第i个节点,需要考虑1作为根节点直到i作为根节点的情况,所以需要累加
// 一共i个节点,对于根节点j时,左子树的节点个数为j-1,右子树的节点个数为i-j
dp[i] += dp[j - 1]*dp[i - j];
}
}
return dp[n];
}
}
总结复盘
- 总耗时:01:36:41