系列文章目录(持续更新)
第一章 动态规划
第二章 递归 (待写)
第三章 排序 (待写)
第四章 二分查找 (待写)
第五章 指针相关 (待写)
一、动态规划(DP)
算法题,都是套路,多做,多练习,就会有很大提高,加油,打工人!!!
本章我们来研究动态规划
二、使用步骤
1.分析问题
分析具体问题,如何将大问题转化为小问题
2.套路步骤
1.明确dp的定义和下标的含义
dp[i] 表示值,个数,前i个值。。。。
2.递推公式
从前推导后面的,还是从后推导前面的
3.dp数组如何初始化
初始1维,2维数组的选择
4.遍历顺序
(从开头还是后面)
(从上面还是下面)
5.打印dp数组
看看dp的输出与你的想法是否相同,进行修改
3.题目示范
给你一个字符串 s,找到 s 中最长的回文子串。
分析问题
"回文串"定义:babad 中bab,aba都是回文串
cbbd中bb是回文串
本题求最长回文串:
思路:
我们可以用一个区间来表示回文串的下标范围,
每次(区间右侧-区间左侧) 大于 当前的结果数组的长度,就更新结果数组
套路解法
- dp[i][j]来表示 字符串 i 到 j 之间是否是回文串
- 递推公式
dp[i][j] 是否为回文串,约束1:下标 i 和 j 的字符 是否相同
约束2:下标 i+1 到j-1之间的字符是否是回文串
(延伸出 可能i和j相连:j-i<2)
得到如下递归公式:
dp[i][j] = s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1])
- dp数组如何初始化
这里直接创建二维数组即可,创建一个矩阵,长i,宽j都等于s的长度 - 遍历顺序
本题可以逆序,也可以正序,但是需要保证 j>=i - 打印dp
判断是否正确 - 最后根据题目 截取最大的回文串
代码如下
var longestPalindrome = function (s) {
var n = s.length
var res = ''
var dp = new Array(n)
for (let i = 0; i < n; i++) {
dp[i] = new Array(n).fill(0)
}
for (let i = n - 1; i >= 0; i--) {
for (let j = i; j < n; j++) {
dp[i][j] = s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1])
if (dp[i][j] && j - i + 1 > res.length) {
res = s.substring(i, j + 1)
}
}
}
return res
};
总结
遇到这类问题,按如下步骤进行:
1.分析问题
2.带入套路公式,进行解决