返回

LeetCode 5:破解回文密码

闲谈

探索LeetCode第5题“最长回文子串”的巧妙解法,一起走进回文的奇妙世界。JavaScript代码清晰易懂,一步步带你找出最长的回文子串,让你对回文子串的本质有更深刻的理解。

任务解读

  • 题目要求:给定一个字符串,找出其中最长的回文子串。
  • 回文子串定义:从左向右读和从右向左读都一样的字符串。例如,“aba”和“abba”都是回文子串。

算法思路

  • 动态规划:
    • 构建一个二维表格dp,其中dp[i][j]表示字符串s中从第i个字符到第j个字符构成的子串是否为回文子串。
    • 根据子串的长度递增,从长度为2的子串开始,依次判断所有长度的子串是否为回文子串。
    • 对于长度为2的子串,如果两个字符相同,则dp[i][j]为true,否则为false。
    • 对于长度大于2的子串,如果dp[i+1][j-1]为true且s[i]等于s[j],则dp[i][j]为true,否则为false。

代码实现

/**
 * 求字符串最长回文子串
 * @param {string} s
 * @return {string}
 */
const longestPalindrome = (s) => {
  if (s.length < 2) {
    return s;
  }

  // 构建dp表格
  const dp = Array(s.length).fill(0).map(() => Array(s.length).fill(false));

  // 长度为2的子串
  for (let i = 0; i < s.length - 1; i++) {
    dp[i][i] = true;
    if (s[i] === s[i + 1]) {
      dp[i][i + 1] = true;
    }
  }

  // 长度大于2的子串
  let maxLength = 1;
  let start = 0;
  for (let length = 3; length <= s.length; length++) {
    for (let i = 0; i <= s.length - length; i++) {
      const j = i + length - 1;
      if (dp[i + 1][j - 1] && s[i] === s[j]) {
        dp[i][j] = true;
        if (length > maxLength) {
          maxLength = length;
          start = i;
        }
      }
    }
  }

  return s.substring(start, start + maxLength);
};

示例

console.log(longestPalindrome("babad")); // "bab"
console.log(longestPalindrome("cbbd")); // "bb"
console.log(longestPalindrome("a")); // "a"
console.log(longestPalindrome("ac")); // "a"
console.log(longestPalindrome("abcba")); // "abcba"

结语

回文子串问题是一个经典的算法问题,理解其本质有助于我们解决更多复杂的问题。LeetCode第5题“最长回文子串”就是一个很好的例子,它不仅考察了我们的算法设计能力,也考验了我们的编码能力。通过这篇题解,希望你能对回文子串问题有更深入的理解,并能运用JavaScript轻松解决类似的问题。