update dp

This commit is contained in:
ranwenjie
2021-11-15 01:44:14 +08:00
parent ec09f22df4
commit 81e6ec3f53
3 changed files with 57 additions and 6 deletions
+24 -3
View File
@@ -25,7 +25,7 @@ DP通常基于一个递推公式及一个(或多个)初始状态,当前子问
* 凑零钱问题 * 凑零钱问题
* 股票问题 [代码参考这里](https://github.com/nonstriater/deep-in-java/blob/master/src/main/java/com/nonstriater/deepinjava/algo/list/stock/BestChance.java) * 股票问题 [代码参考这里](https://github.com/nonstriater/deep-in-java/blob/master/src/main/java/com/nonstriater/deepinjava/algo/list/stock/BestChance.java)
* 打家劫舍问题 : num[i] 代表第i个房子中的现金数目,从房子中取钱的最大数目,约束是相邻房子的钱不能同时取出 * 打家劫舍问题 : num[i] 代表第i个房子中的现金数目,从房子中取钱的最大数目,约束是相邻房子的钱不能同时取出
* 接雨水问题 : * 接雨水问题 :num[i]表示柱子高度,计算下雨之后能接多少雨水
* 青蛙跳阶问题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。 * 青蛙跳阶问题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。
* 最小编辑距离 * 最小编辑距离
* 最长递增子序列 (LIS Longest Increasing Subsequence),如`【5,6,7,3,2,8】` 最长子序列 `【5,6,7,8】`, 输出4 * 最长递增子序列 (LIS Longest Increasing Subsequence),如`【5,6,7,3,2,8】` 最长子序列 `【5,6,7,8】`, 输出4
@@ -56,8 +56,6 @@ DP通常基于一个递推公式及一个(或多个)初始状态,当前子问
### DP VS 分治法 ### DP VS 分治法
与[分治法](分治算法.md)不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。 与[分治法](分治算法.md)不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。
@@ -105,6 +103,29 @@ for 状态1 in 状态1的所有取值:
```Java ```Java
//递归解法,处理重叠子问题, 使用 dp[amount+1] 备忘录
int coinChange2(int[] coins, int amount) {
int[] dp = new int[amount + 1];
// 数组大小为 amount + 1,初始值也为 amount + 1
// 为啥 dp 数组初始化为 amount + 1 呢,因为凑成 amount 金额的硬币数最多只可能等于 amount(全用 1 元面值的硬币),所以初始化为 amount + 1 就相当于初始化为正无穷
Arrays.fill(dp, amount + 1);
// base case
dp[0] = 0;
// 外层 for 循环在遍历所有状态的所有取值
for (int i = 0; i < dp.length; i++) {
// 内层 for 循环在求所有选择的最小值
for (int coin : coins) {
// 子问题无解,跳过
if (i - coin < 0) {
continue;
}
dp[i] = Math.min(dp[i], 1 + dp[i - coin]);
}
}
return (dp[amount] == amount + 1) ? -1 : dp[amount];
}
``` ```
@@ -193,7 +193,7 @@ int longest_common_subsequence(const char *s1,const char *s2, char *common){
``` ```
## 对称子字符串的最大长度 ## 对称子字符串的最大长度 (最长回文子串)
题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。 题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。
@@ -215,6 +215,37 @@ int max_symmetrical_char_length(const char *scr){
``` ```
```Java
public String longestPalindrome(String s) {
String res = "";
for (int i = 0; i < s.length(); i++) {
// 以 s[i] 为中心的最长回文子串
String s1 = palindrome(s, i, i);
// 以 s[i] 和 s[i+1] 为中心的最长回文子串
String s2 = palindrome(s, i, i + 1);
// res = longest(res, s1, s2)
res = res.length() > s1.length() ? res : s1;
res = res.length() > s2.length() ? res : s2;
}
return res;
}
//实现一个函数来寻找最长回文串
String palindrome(String s, int l, int r) {
// 防止索引越界
while (l >= 0 && r < s.length()
&& s.charAt(l) == s.charAt(r)) {
// 向两边展开
l--; r++;
}
// 返回以 s[l] 和 s[r] 为中心的最长回文串
return s.substring(l + 1, r);
}
```
## 子串匹配的个数 ## 子串匹配的个数
@@ -81,7 +81,6 @@ int findaddends(int *data,int length,int sum,int *a,int *b);
## 求子数组的最大和(最大字段和) ## 求子数组的最大和(最大字段和)
输入一个整形数组,数组里有正数也有负数。 输入一个整形数组,数组里有正数也有负数。
@@ -91,7 +90,7 @@ int findaddends(int *data,int length,int sum,int *a,int *b);
例如输入的数组为`1, -2, 3, 10, -4, 7, 2, -5` ,和最大的子数组为`3, 10, -4, 7, 2` ,因此输出为该子数组的和18。 例如输入的数组为`1, -2, 3, 10, -4, 7, 2, -5` ,和最大的子数组为`3, 10, -4, 7, 2` ,因此输出为该子数组的和18。
1. 蛮力法 fmax(i,j) 找出最大的值,3重循环 ,复杂度 0(n^3) 1. 蛮力法 fmax(i,j) 找出最大的值,3重循环 ,复杂度 0(n^3)
2. maxendindhere保存当前累加的和,如果<0,就把maxendinghere清零 , max保存最终的最大和; 如果都是负数 2. `动态规划` maxendindhere保存当前累加的和,如果<0, 就把maxendinghere清零 , max保存最终的最大和; 如果都是负数
``` ```
int maxSumOfVector(int *data,int length){ int maxSumOfVector(int *data,int length){