动态规划
思路: 如果字符串首尾字符相同且去除首尾的子串也为回文串 那么 该字符串必定为回文串。
那么首先 所有长度为1的 单个字符都为回文。
然后从长度为2开始依次遍历每个长度下的子串 ,并记录该子串是否为回文。
由于长度是从短到长,也就是遍历到的字符串其去除首尾的子串必定已经得到判断。
所以只需要判断该串的首尾字符是否相等以及其子串是否为回文即可判断该串是否为回文串。
如果是回文串记录其长度即可
代码
var longestPalindrome = function (s) {
if (s.length < 2) return s
let begin = 0,
j = 0,
n = s.length,
max = 1,
dp = [];
// 初始化dp,所有长度为1的字符串都是回文串
for (let i = 0; i < n; i++) {
dp[i] = new Array(n).fill(true)
}
// 以长度从短到长开始遍历
for (let L = 2; L <= n; L++) {
for (let i = 0; i < n; i++) {
j = i + L - 1
// 右边界超出长度直接退出循环
if (j > n - 1) break;
// 如果左右边缘不相等 肯定不是回文串
if (s[i] != s[j]) {
dp[i][j] = false
} else {
// 长度为2且首尾相同肯定为回文串
if (j - i < 3) {
dp[i][j] = true
} else {
// 向内收缩,因为内部都已经判断过是否为回文
dp[i][j] = dp[i + 1][j - 1]
}
}
// 如果当前是回文串且长度大于所记录的最大长度
if (dp[i][j] && (j - i + 1) > max) {
console.log('i',i,'j',j,s[i],s[j])
begin = i
max = j - i + 1
console.log('begin',begin,'max',max)
}
}
}
return s.substr(begin, max)
};
中心扩散
思路 动态规划是从外到内剥离,那中心扩散就是从中心往外逐层扩散。以单个字符往两边扩散,如果两边字符相等则是回文串。扩散又分两种情况 分别是以该字符为中心,和以该字符和下一个字符的空隙为中心
代码
var longestPalindrome = function (s) {
const n = s.length
if (n == 1) return s
let start = 0,
end = 0;
const expandFcn = (left, right) => {
while (left >= 0 && right < n && s[left] == s[right]) {
--left;
++right;
}
// console.log('right', right, 'left', left)
return right - left - 1
}
for (let i=0; i < n; i++) {
let len = Math.max(expandFcn(i, i), expandFcn(i, i + 1))
if (len > (end - start)) {
start = i - parseInt((len - 1) / 2)
end = i + parseInt(len / 2)
}
};
return s.substring(start, end + 1)
};