持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
思路分析:
最长回文子串这道题和和最长无重复子串不同,不应该单纯通过滑动窗口的方法来解决,因为回文子串要判断子串是否构成回文,需要每次加入之后都对子串进行校验是否符合回文标准,只有暴力破解才会单纯的使用滑动窗口的方式来解决问题。
那么我们思考一个问题,回文子串的要求是整体字符串都符合aba或者aabb的形式,也就是需要整体字符串是一个对称的字符串。那么就说明回文字符串的左右边界一定是对称的,可以由此得出,我们可以使用中心扩散法,我们判断的时候可以从中间往两边扩散,如果两边相同则可以继续往外扩散,这样我们可以得到由其中一个点扩散出来的最大回文子串,然后继续比较就可以得到最终的最长回文子串。
var longestPalindrome = function(s) {
let obj = {
num:0,
string:''
}
let deep = (left,right,num=1)=>{
if(!s[left]||!s[right])return
if(s[left]===s[right]){
deep(left-1,right+1,num+2)
if(num+2>obj.num){
obj.num = num+2
obj.string = s.slice(left,right+1)
}
}else if(num>obj.num){
obj.num = num
obj.string = s.slice(left+1,right)
}
}
for(let i=0;i<s.length;i++){
if(s[i]===s[i+1]){
deep(i-1,i+2,2)
if(obj.num<=2){
obj.string = s[i]+s[i+1]
obj.num = 2
}
}
deep(i-1,i+1,1)
if(obj.num<=1){
obj.string = s[i]
}
}
return obj.string
};
在使用中心扩散法的时候,我们会对每个字符扩散出来的回文字符串进行检测,这样其实会有许多的性能上的浪费,我们在扩散的时候可以使用备忘录来进行记录已经确定过的每一个回文字符串,当我们再检测时可以直接使用。这样通过空间来换时间。
var longestPalindrome = function(s) {
let n = s.length;
let res = '';
let dp = Array.from(new Array(n),() => new Array(n).fill(false));
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;
};