React Router

016-最长回文子串 (Longest Palindromic Substring)

LeetCode 第5题 - 最长回文子串的详细题解

题目描述

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

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例

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

输入:s = "cbbd"
输出:"bb"

解题思路

使用中心扩展法,遍历字符串的每个位置,以该位置为中心向两边扩展,寻找最长的回文子串。需要同时考虑奇数长度和偶数长度的回文串。

JavaScript 解决方案

/**
 * @param {string} s
 * @return {string}
 */
const longestPalindrome = (s) => {
    if (s.length < 2) return s;
    
    let start = 0;
    let maxLength = 1;
    
    // 中心扩展函数
    const expandAroundCenter = (left, right) => {
        while (left >= 0 && right < s.length && s[left] === s[right]) {
            const currentLength = right - left + 1;
            if (currentLength > maxLength) {
                start = left;
                maxLength = currentLength;
            }
            left--;
            right++;
        }
    };
    
    // 遍历每个位置作为中心
    for (let i = 0; i < s.length; i++) {
        // 奇数长度的回文串
        expandAroundCenter(i, i);
        // 偶数长度的回文串
        expandAroundCenter(i, i + 1);
    }
    
    return s.substring(start, start + maxLength);
};

复杂度分析

  • 时间复杂度:O(n²),其中 n 是字符串长度
  • 空间复杂度:O(1),只使用了常数额外空间

测试用例

// 测试函数
const testLongestPalindrome = () => {
    const testCases = [
        {
            s: "babad",
            expected: "bab"
        },
        {
            s: "cbbd",
            expected: "bb"
        },
        {
            s: "a",
            expected: "a"
        },
        {
            s: "ac",
            expected: "a"
        },
        {
            s: "aaaa",
            expected: "aaaa"
        },
        {
            s: "abcba",
            expected: "abcba"
        },
        {
            s: "racecar",
            expected: "racecar"
        },
        {
            s: "abacdfgdcaba",
            expected: "aba"
        }
    ];

    testCases.forEach((testCase, index) => {
        const result = longestPalindrome(testCase.s);
        const passed = result === testCase.expected;
        console.log(`测试用例 ${index + 1}: ${passed ? '通过' : '失败'}`);
        console.log(`输入: s = "${testCase.s}"`);
        console.log(`期望: "${testCase.expected}", 实际: "${result}"\n`);
    });
};

// 运行测试
testLongestPalindrome();

关键点总结

  1. 中心扩展法:以每个位置为中心向两边扩展
  2. 奇偶处理:同时考虑奇数长度和偶数长度的回文串
  3. 边界检查:确保扩展时不会越界
  4. 长度更新:实时更新最长回文串的起始位置和长度
  5. 字符比较:比较左右两边的字符是否相等

总结

这道题考察了以下重点:

  • 中心扩展技巧:理解回文串的对称性质
  • 字符串处理:如何高效地处理字符串子串
  • 边界处理:对字符串边界和特殊情况的处理
  • 算法优化:通过中心扩展避免重复计算

中心扩展法是最优解,时间复杂度为 O(n²),空间复杂度为 O(1)。在实际面试中,建议先提出动态规划解法,然后优化到中心扩展解法。