📅  最后修改于: 2023-12-03 15:10:45.581000             🧑  作者: Mango
回文是指从前往后和从后往前读都一样的字符串。例如,"racecar" 和 "level" 都是回文字符串。在字符串中查找最长回文子串是一道经典的编程问题。本文将介绍 JavaScript 中查找最长回文的算法。
我们可以使用动态规划算法来查找最长回文子串。该算法的基本思路是:
dp
,其中 dp[i][j]
表示字符串从第 i
个字符到第 j
个字符是否为回文串。i == j
时,即只有一个字符时,肯定是回文串。i + 1 == j
时,即只有两个字符时,当且仅当这两个字符相等时,才是回文串。i + 1 < j
时,如果子串 s[i+1, ..., j-1]
是回文串,并且 s[i] == s[j]
,则 s[i, ..., j]
也是回文串。根据上述规则,我们可以得到状态转移方程:
dp[i][j] = true i == j
s[i] == s[j] i + 1 == j
s[i] == s[j] && dp[i+1][j-1] i + 1 < j
最后,我们只需要在 dp
数组中找到长度最长且为回文串的子串即可。
下面是 JavaScript 实现动态规划算法查找最长回文子串的代码:
/**
* 查找最长回文子串
* @param {string} s
* @return {string}
*/
function longestPalindrome(s) {
const n = s.length;
const dp = Array.from({ length: n }, () => Array.from({ length: n }, () => false));
let ans = '';
for (let l = 0; l < n; ++l) {
for (let i = 0; i + l < n; ++i) {
const j = i + l;
if (l == 0) {
dp[i][j] = true;
} else if (l == 1) {
dp[i][j] = s[i] == s[j];
} else {
dp[i][j] = s[i] == s[j] && dp[i+1][j-1];
}
if (dp[i][j] && l + 1 > ans.length) {
ans = s.substring(i, j + 1);
}
}
}
return ans;
}
下面是使用 Jasmine 对该算法进行简单测试的代码:
describe('longestPalindrome', () => {
it('should return empty string when input is empty', () => {
expect(longestPalindrome('')).toEqual('');
});
it('should return single character when input only has one character', () => {
expect(longestPalindrome('a')).toEqual('a');
});
it('should return longest palindrome for odd length input', () => {
expect(longestPalindrome('babad')).toEqual('bab');
});
it('should return longest palindrome for even length input', () => {
expect(longestPalindrome('cbbd')).toEqual('bb');
});
});
该算法的时间复杂度为 $O(n^2)$,其中 $n$ 是输入字符串的长度。具体来说,该算法需要枚举所有可能的子串,每个子串需要 $O(1)$ 的时间判断是否为回文串。该算法的空间复杂度也是 $O(n^2)$,因为需要一个二维数组来存储是否为回文串的状态。而且,由于该算法使用了动态规划的思想,算法的实现较为简单,容易理解和维护。