LeetCode #5 Medium

最长回文子串

更新于:2026-01-26 在 LeetCode 上查看

题目描述

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

示例

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

我的解题过程

首先想的就是双指针 然后反转字符串 判断是否是回文字符串

function longestPalindrome(s: string): string {
  if (s.length < 2) return s;

  let max = 0;
  let res = s[0];
  for (let i = 0; i < s.length - 1; i++) {
    for (let j = s.length - 1; j > 0; j--) {
      const str = s.substring(i, j + 1);

      if (str === str.split("").reverse().join("") && str.length > max) {
        max = str.length;
        res = str;
      }
    }
  }
  return res;
}

这样写完运行没问题 但是提交后发现 超时了

所以看了下解题思路 常见的是中心扩展法 和动态规划法

中心扩展法

把每一个字符串的位置作为中心点 向两边扩展 判断是否是回文字符串

错误示例代码:

function longestPalindrome(s: string): string {
  let cur = 0;
  let res = "";

  for (let i = 0; i < s.length - 1; i++) {
    let preIndex = i - 1;
    let nextIndex = i + 1;

    while (preIndex >= 0 && nextIndex < s.length && s[preIndex] === s[nextIndex]) {
      res = s.substring(preIndex, nextIndex + 1);
      preIndex--;
      nextIndex++;
    }
  }

  return res;
}

运行后第一个测试用例是对的 但是第二个就错了 因为可能存在当前的中心点是两个字符(偶数)的情况

所以又出现了一个错误的代码:

function longestPalindrome(s: string): string {
  if (s.length < 2) return s;

  let cur = 0;
  let res = "";

  for (let i = 0; i < s.length - 1; i++) {
    let preIndex = i - 1;
    let nextIndex = i + 1;

    while (
      (preIndex >= 0 && nextIndex < s.length && s[preIndex] === s[nextIndex]) ||
      (preIndex >= 0 && nextIndex < s.length && s[i] === s[nextIndex])
    ) {
      const isOdd = preIndex >= 0 && nextIndex < s.length && s[preIndex] === s[nextIndex];
      const isEven = preIndex >= 0 && nextIndex < s.length && s[i] === s[nextIndex];
      res = s.substring(isOdd ? preIndex : i, nextIndex + 1);
      preIndex--;
      nextIndex++;
    }
  }

  return res;
}

这个代码把奇数和偶数放到一起处理了 但是两个的处理其实是不同的 所以还是错的

最终正确代码如下:

function longestPalindrome(s: string): string {
  if (s.length < 2) return s;

  let res = s[0];

  for (let i = 0; i < s.length; i++) {
    // ---------- 奇数回文 ----------
    let preIndex = i - 1;
    let nextIndex = i + 1;

    while (preIndex >= 0 && nextIndex < s.length && s[preIndex] === s[nextIndex]) {
      const cur = s.substring(preIndex, nextIndex + 1);
      if (cur.length > res.length) {
        res = cur;
      }
      preIndex--;
      nextIndex++;
    }

    // ---------- 偶数回文 ----------
    let evenPreIndex = i;
    let evenNextIndex = i + 1;

    while (evenPreIndex >= 0 && evenNextIndex < s.length && s[evenPreIndex] === s[evenNextIndex]) {
      const cur = s.substring(evenPreIndex, evenNextIndex + 1);
      if (cur.length > res.length) {
        res = cur;
      }
      evenPreIndex--;
      evenNextIndex++;
    }
  }

  return res;
}

运行通过 所有测试用例都正确 也没有超时 优化后代码

function longestPalindrome(s: string): string {
    if (s.length < 2) return s;

    let res = s[0];

    const expandAroundCenter = (left: number, right: number) => {
        while (left >= 0 && right < s.length && s[left] === s[right]) {
        const cur = s.substring(left, right + 1);
        if (cur.length > res.length) {
            res = cur;
        }
        left--;
        right++;
        }
    };

    for (let i = 0; i < s.length; i++) {
        // 奇数回文
        expandAroundCenter(i, i);
        // 偶数回文
        expandAroundCenter(i, i + 1);
    }

    return res;
    }
    ```