mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-11 04:54:51 +08:00
增加5. 最长回文子串 JavaScript版本
This commit is contained in:
@ -297,6 +297,117 @@ class Solution:
|
||||
## JavaScript
|
||||
|
||||
```js
|
||||
//动态规划解法
|
||||
var longestPalindrome = function(s) {
|
||||
const len = s.length;
|
||||
// 布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false
|
||||
let dp = new Array(len).fill(false).map(() => new Array(len).fill(false));
|
||||
// left起始位置 maxlenth回文串长度
|
||||
let left = 0, maxlenth = 0;
|
||||
for(let i = len - 1; i >= 0; i--){
|
||||
for(let j = i; j < len; j++){
|
||||
// 情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串 j - i == 0
|
||||
// 情况二:下标i 与 j相差为1,例如aa,也是文子串 j - i == 1
|
||||
// 情况一和情况二 可以合并为 j - i <= 1
|
||||
// 情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]===true
|
||||
if(s[i] === s[j] && (j - i <= 1 || dp[i + 1][j - 1])){
|
||||
dp[i][j] = true;
|
||||
}
|
||||
// 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置
|
||||
if(dp[i][j] && j - i + 1 > maxlenth) {
|
||||
maxlenth = j - i + 1; // 回文串长度
|
||||
left = i; // 起始位置
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.substr(left, maxlenth); // 找到子串
|
||||
};
|
||||
|
||||
//双指针
|
||||
var longestPalindrome = function(s) {
|
||||
let left = 0, right = 0, maxLength = 0;
|
||||
const extend = (s, i, j, n) => {// s为字符串 i,j为双指针 n为字符串长度
|
||||
while(i >= 0 && j < n && s[i] === s[j]){
|
||||
if(j - i + 1 > maxLength){
|
||||
left = i; // 更新开始位置
|
||||
right = j; // 更新结尾位置
|
||||
maxLength = j - i + 1; // 更新子串最大长度
|
||||
}
|
||||
// 指针移动
|
||||
i--;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
for(let i = 0; i < s.length; i++){
|
||||
extend(s, i, i, s.length); // 以i为中心
|
||||
extend(s, i, i + 1, s.length); // 以i和i+1为中心
|
||||
}
|
||||
return s.substr(left, maxLength);
|
||||
};
|
||||
|
||||
//Manacher算法
|
||||
var longestPalindrome = function(s) {
|
||||
const len = s.length;
|
||||
if(len < 2) return s;
|
||||
let maxLength = 1, index = 0;
|
||||
//Manacher算法,利用回文对称的性质,根据i在上一个回文中心的臂长里的位置去判断i的回文性
|
||||
//需要知道上一个回文中心,以及其臂长
|
||||
let center = 0;
|
||||
//注意这里使用了maxRight的而不是真实的臂长length,因为之后需要判断i在臂长的什么位置
|
||||
//如果这里臂长用了length,之后还要 计算i - center 去和 length比较,太繁琐
|
||||
let maxRight = 0;
|
||||
//考虑到回文串的长度是偶数的情况,所以这里预处理一下字符串,每个字符间插入特殊字符,把可能性都化为奇数
|
||||
//这个处理把回文串长度的可能性都化为了奇数
|
||||
//#c#b#b#a#
|
||||
//#c#b#a#b#d#
|
||||
let ss = "";
|
||||
for(let i = 0; i < s.length; i++){
|
||||
ss += "#"+s[i];
|
||||
}
|
||||
ss += "#";
|
||||
//需要维护一个每个位置臂长的信息数组positionLength
|
||||
const pl = new Array(ss.length).fill(0);
|
||||
//这里需要注意参考的是i关于center对称的点i'的回文性
|
||||
//i' = 2*center - i;
|
||||
//所以列下情况:
|
||||
//1.i>maxRight,找不到i',无法参考,自己算自己的
|
||||
//2.i<=maxRight:
|
||||
//2.1 i<maxRight-pl[i'],pl[i']的臂长没有超过center的臂长,根据对称性,pl[i] = pl[i']
|
||||
//2.2 i=maxRight-pl[i'],pl[i']的臂长刚好等于center的臂长,根据对称性,pl[i] >= pl[i‘],大多少需要尝试扩散
|
||||
//2.3 i>maxRight-pl[i'],pl[i']的臂长超过了center的臂长,根据对称性,i中心扩散到MaxRight处,
|
||||
// s[2*i-maxRight] !== s[MaxRight]必不相等,所以pl[i] = maxRight-i;
|
||||
//总结就是pl[i] = Math.min(maxRight-i,pl[i']);提示i<maxRight-pl[i'] 也可写成 pl[i']<maxRight-i
|
||||
//0没有意义,从1开始计算
|
||||
for(let i = 1; i < ss.length; i++){
|
||||
if(i <= maxRight){//可以参考之前的
|
||||
pl[i] = Math.min(maxRight - i, pl[2 * center - i]);
|
||||
//尝试中心扩散
|
||||
}
|
||||
//注意到i<maxRight时都要尝试中心扩散,所以写else完全无意义,把中心扩散的代码写在下面
|
||||
// else{//i不在之前回文中心的臂长范围里,之前的信息就完全无法参考,只能从i中心扩散把,然后去维护maxRight和center的定义
|
||||
//尝试中心扩散
|
||||
//这里不要动center和maxRight
|
||||
// center = i;
|
||||
// maxRight = pl[i] + i + 1;
|
||||
let right = pl[i] + i + 1;
|
||||
let left = i - pl[i] - 1;
|
||||
while (left >= 0 && right<ss.length && ss[left] === ss[right]) {
|
||||
right++;
|
||||
left--;
|
||||
pl[i]++;
|
||||
}
|
||||
// }
|
||||
if(pl[i] + i > maxRight){
|
||||
center = i;
|
||||
maxRight = pl[i] + i;
|
||||
}
|
||||
if (pl[i] * 2 + 1 > maxLength){
|
||||
maxLength = pl[i]*2+1;
|
||||
index = i - pl[i];
|
||||
}
|
||||
}
|
||||
return ss.substr(index, maxLength).replace(/#/g,"");
|
||||
};
|
||||
```
|
||||
|
||||
-----------------------
|
||||
|
Reference in New Issue
Block a user