题目:
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
核心思路:【动态规划】
动态规划:填dp表、当前ij状态、过去ij状态、如何联合得到输出、边界条件。
-
step1.定义状态:题目让我们求什么,就把什么设置为状态,题目求s中最长的回文子串,那就判断所有子串是否为回文子串,选出最长的。因此,
dp[i][j]表示str[i:j+1]是否为回文子串(这里+1是为了构造闭区间); -
step2.状态转移方程:对空间进行分类讨论(当前ij状态、过去ij状态 如何联合得到输出)
状态方程: dp[i][j] = str[i] === str[j] && dp[i+1][j-1]
当前ij状态:头尾必须相等(s[i]==s[j])
过去ij状态:去掉头尾之后还是一个回文(dp[i+1][j-1] is True)
边界条件:只要是找过去ij状态的时候,就会涉及边界条件(即超出边界情况处理)
边界条件:
- 限定
i <= j - 当
i==j时一定是回文 j-1-(i+1)<=0,即j-i<=2时,只要当s[i]==s[j]时就是回文,不用判断dp[i+1][j-1]为dp[i][j]截取的子串。白话:长度为1,2,3的字符串,判定回文,只需要确认两边的字符是否相同即可;- 避免
j-1 > i+1(需要由前序状态递推)
-
step3.初始状态:这里已经直接判断
j-i<=2的情况了,因此用不到初始状态,可以不设 -
step4.输出内容:每次发现新回文都比较一下长度,记录i与长度
老样子,先整个样例,平铺一下所有解,再结合代码分析。
解:
var longestPalindrome = (str) => {
if (!str) return '';
let len = str.length;
if (len === 1) {
return str;
}
let start = 0;
let max_len = 1;
let cur_len = 0;
let dpArr = Array.from(Array(len), () => new Array(len).fill('')) //创建dp表
// 动态规划:填dp表、当前ij状态、过去ij状态、如何联合得到输出、边界条件
// step1:定义状态:题目让我们求什么,就把什么设置为状态,题目求s中最长的回文子串,那就判断所有子串是否为回文子串,选出最长的
// 因此:dp[i][j]表示str[i:j+1]是否为回文子串(这里+1是为了构造闭区间)
// step2:状态转移方程:对空间进行分类讨论(当前ij状态、过去ij状态 如何联合得到输出)
// 当前ij状态:头尾必须相等(s[i]==s[j])
// 过去ij状态:去掉头尾之后还是一个回文(dp[i+1][j-1] is True)
// 边界条件:只要是找过去ij状态的时候,就会涉及边界条件(即超出边界情况处理)
for (let j = 0; j < len; j++) {
for (let i = 0; i <= j; i++) { // 限定i <= j
if (j - i <= 2) {
// 边界条件,避免j-1 > i+1 (前面状态) 即i===j的情况,这种不适用递推式。
// 长度为1,2,3的字符串,判定回文,只需要确认两边的字符是否相同即可。
// 当i==j时一定是回文
// j-1-(i+1)<=0,即j-i<=2时,只要当s[i]==s[j]时就是回文,不用判断dp[i+1][j-1] 为dp[i][j] 截取的子串
if (str[i] === str[j]) {
dpArr[i][j] = true;
cur_len = j - i + 1;
}
} else {
if (str[i] === str[j] && dpArr[i + 1][j - 1]) { // j-i > 2就不会出现i+1 > j-1 的情况
// 递推式
dpArr[i][j] = true;
cur_len = j - i + 1;
}
}
// step3: 初始状态:这里已经直接判断j-i<=2的情况了,因此用不到初始状态,可以不设
// step4: 输出内容:每次发现新回文都比较一下长度,记录i与长度
if (dpArr[i][j]) {
if (cur_len > max_len) {
start = i;
max_len = cur_len;
}
}
}
}
return str.substr(start, max_len)
}
console.log(longestPalindrome("aacabdkacaa"))
———— 前端、Javascript实现、算法、刷题、leetcode