算法--最长回文子串

127 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

题目

leetcode 5. 最长回文子串

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

示例:

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

题解

回文的意思是正着念和倒着念一样,比如abcba,正反都是一样的字符串我们就可以当作回文字符串。对于一个子串而言,如果它是回文串,并且长度大于2,那么将它首尾的两个字母去除之后,它仍然是个回文串。

暴力解法:

通过双指针遍历每一种字串,然后判断该字串是否是回文字符串,然后在所有回文子串中返回最长的一个即可。

var longestPalindrome = function (s) {
    if(s.length === 1){
        return s
    }
    const arr = s.split('');
    let l = 0;
    const len = arr.length;
    let r = l + 1;
    const res = [];
    while (l < len - 1) {
        while (r < len) {
            const subArr = arr.slice(l, r + 1);
            if (isPalindrome(subArr)) {
                res.push(subArr.join(''))
            }
            r++;
        }
        l++;
        r = l + 1;
    }
    if(res.length === 0){
        return arr[0]
    }
    res.sort((a,b)=>a.length-b.length);
    return res[res.length - 1]
};

function isPalindrome(arr) {
    const subArr = [...arr].reverse();
    if (JSON.stringify(subArr) === JSON.stringify(arr)) {
        return true
    }
    return false;
}

代码详解

首先写一个辅助函数 isPalindrome 来帮助我们判断字符串是否是回文字符串。 我们定义变量l,r为快慢指针,res来保存回文子串。循环遍历每一个子串,将符合的回文子串加入到res数组中。最后返回长度最大的回文子串即可得出结果。

中心扩散:

从中间字符串开始往两边扩散,相比于暴力解法速度提升了很多。

var longestPalindrome = function (s) {
  if(s.length === 1){
      return s
  }
  const len = s.length;
  let max = ''
  for (let i = 0; i <len; i++) {
    fn(i, i)
    fn(i, i + 1)
  }
  function fn (l, r) {
    while (l >= 0 && r < s.length && s[l] === s[r]) {
      l--
      r++
    }
    const maxStr = s.slice(l + 1, r)
    if (maxStr.length > max.length) {
      max = maxStr
    }
  }
  return max
}

代码详解

首先写一个辅助函数fn来完成扩散的运算,有两种情况一种是奇数个字符串,一种是偶数个字符串所以执行两次来完成整个回文子串的运算。