JS实现的算法(六)--最长回文子串

5,599 阅读2分钟

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设s 的最大长度为 1000。 (题目转自leetcode)

示例 1:

输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2:

输入: "cbbd" 输出: "bb"

解:

我想了两种方法,暴力循环和动态规划

解法一:暴力循环

var longestPalindrome = function(s) {
  let str = "";
  for(let i = 0; i < s.length; i++) {
      for(let j = i + 1; j <= s.length; j++) {
          const temp = s.slice(i, j);
          if(temp == temp.split("").reverse().join("") && temp.length > str.length) {
              str = temp;
          }
      }
  }
  return str;
};

解法二:动态规划

首先考虑如果字符串长度为1,那么答案就是其本身

如果字符串长度等于2,那么如果s[i] == s[j] 则说明该字符串为回文

那么如果长度大于2呢?s[i] == s[j]的情况下s[i + 1] == s[j-1],也说明该字符串为回文

如此推论,结果如下:

var longestPalindrome = function(s) {
  if (s.length == 1) {
    // 长度1,返回本身
    return s;
  }
  
  // 创建二阶数组存储从j到i是否是回文数组,0为不回文,1为回文
  let arr = [];
  for (let i = 0; i < s.length; i ++) {
      arr[i] = [];
  };
  
  // 存储最长回文子串的起始位置
  let begin = 0;
  // 存储最长子串的长度
  let max = 0;

  for(let i = 0; i < s.length; i ++) {
    let j = 0;
    while (j <= i) {
      // 如果 i-j <= 1 时,说明i位置和j位置要么是重合的,要么是相邻的,即为最后一次查找
      // 否则继续查询[j + 1]到[i - 1]是否为回文
      if( s[j] == s[i] && (i - j <= 1 || arr[j+1][i-1] ) ) {
        // 如果符合上述条件,说明j到i是回文
        arr[j][i] = 1
        if (i - j + 1 > max) {
          // 如果当前子串大于存储的子串长度,则替换之
          begin = j;
          // 注意+1,比如从3到5的长度为3 = 5 - 3 + 1
          max = i - j + 1;
        }
      }
      j ++;
    }
  }
  return s.substr(begin, max);
}