前端算法(5)

82 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

给你一个字符串 s,找到 s 中最长的回文子串。

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。

回文串:正着读和反着读都一样的字符串

解题思路

思路一

我们先从左边的第一个字符开始遍历,利用中心扩散法,核心思路回文串主要分为偶数和奇数,回文串为偶数个的时候 l=i,r=i+1,遇到相同的就直接往两边走,并且判断res.length是不是小于最长回文串的长度 r-l-1, 满足条件就截取字符串, 回文串为奇数时,l=i-1,r=i+1,其余情况同上,边界点为[l+1,R-1],所以最长回文子串的长度为R-1-(l+1)+1=R-L-1

var longestPalindrome = function(s) {
   let res='';
   for(let i=0;i<s.length;i++){
    let l=i-1, r=i+1;
    while(l>=0 && r<s.length && s[l]===s[r]) l--,r++;
    if(res.length <r-l-1) res=s.substr(l+1,r-l-1);
    l=i,r=i+1;
    while(l>=0 && r<s.length && s[l]===s[r]) l--,r++;
    if(res.length <r-l-1) res=s.substr(l+1,r-l-1);
   }
   return res;
};

思路二

我们首先判断字符串为空串或者单字符的情况,直接返回原字符串,回文的状态转移方程是dp[i][j] = s[i] === s[j] && (j - i <= 2 || dp[i + 1] [j - 1] === true),这个题使用的方法是从0点开始取右边index从1到n-1,依次计算出每一个的子范围的回文情况,确认是回文了之后,在判断最大的长度

var longestPalindrome = function(s) {
    if(s.length < 2){
        return s;
    }
    let maxLen = 1;
    let maxStart = 0;
    let maxEnd = 0;
    const length = s.length;
    const dp = Array.from({length}).map(_=>new Array(length).fill(false));
    for(let r = 1; r < length; r++){
        for(let l = 0; l < r; l++){
            if(s[r] === s[l] && (r - l <= 2 || dp[l + 1] [r - 1])){
                dp[l][r] = true;
                if(r -l + 1 > maxLen){
                maxStart = l;
                maxEnd = r;
                maxLen = r - l + 1;
                }   
            }
        }
    }
    return s.substring(maxStart, maxEnd + 1);
};