LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进

题目描述

题目来源 :LeetCode 第 5 题

标签:字符串、动态规划、中心扩展

题目要求 :

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

什么是回文串?

如果一个字符串正着读和反着读是一样的,那么它就是回文串。例如 "aba"、"abba" 都是回文串。

提示与约束条件:

  • 1 <= s.length <= 1000

  • s 仅由数字和英文字母组成

方法一:字符串反转 + 最长公共子串

1. 初始思路

回文串的特性是"正读反读都一样"。一个直观的想法是:将原字符串 s 反转得到 ss,然后寻找 s 和 ss 的最长公共子串(LCS)。这个公共子串理论上就是最长回文子串。

2. 逻辑漏洞与修正

漏洞 :仅仅寻找公共子串是不够的。例如 s = "abacdfgdcaba",反转后 ss = "abacdfgdcaba",两者的最长公共子串是 "abacd",但它并不是回文。

修正 :必须验证找到的公共子串在原字符串中的索引与反转字符串中的索引是否满足对称关系。即:若 s 中起始索引为 i,ss 中起始索引为 j,匹配长度为 len,则必须满足 i + j + len == s.size(),才能保证它是真正的回文。

3. 代码实现

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) {
        if (s.empty()) return "";
        string ss = s;
        reverse(ss.begin(), ss.end());
        string ans = "";
        
        for (int i = 0; i < s.size(); i++) {
            for (int j = 0; j < ss.size(); j++) {
                int len = 0;
                while (i + len < s.size() && j + len < ss.size() && s[i + len] == ss[j + len]) {
                    len++;
                }
                // 核心修正:验证索引对称性
                if (len > ans.size() && i + j + len == s.size()) {
                    ans = s.substr(i, len);
                }
            }
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度 :O(n3)。双层循环枚举起点为 O(n2),内部 while 匹配最坏情况为 O(n)。

  • 空间复杂度 :O(n)。需要存储反转字符串 s。

方法二:中心扩展法(最优解法)

1. 思路转变

放弃"反转匹配"的间接思路,回归回文的本质:对称性 。回文串一定有一个"中心",从这个中心向两边扩展,两边的字符必定相等。

中心可能有两种情况:

  • 奇数长度 :中心是一个字符(如 "aba",中心是 'b')。

  • 偶数长度 :中心是两个字符之间的空隙(如 "abba",中心在两个 'b' 之间)。

我们只需遍历字符串的每一个位置,将其作为中心向两边扩展,记录最长的回文即可。

2. 代码实现

cpp 复制代码
class Solution {
public:
    string longestPalindrome(string s) {
        if (s.empty()) return "";
        int start = 0, maxLen = 1;
        
        for (int i = 0; i < s.size(); i++) {
            // 奇数长度回文扩展
            int len1 = expandAroundCenter(s, i, i);
            // 偶数长度回文扩展
            int len2 = expandAroundCenter(s, i, i + 1);
            
            int len = max(len1, len2);
            if (len > maxLen) {
                maxLen = len;
                start = i - (len - 1) / 2;
            }
        }
        return s.substr(start, maxLen);
    }

private:
    int expandAroundCenter(const string& s, int left, int right) {
        while (left >= 0 && right < s.size() && s[left] == s[right]) {
            left--;
            right++;
        }
        return right - left - 1;
    }
};

复杂度分析

  • 时间复杂度:O(n2)。共有 2n−1个中心,每个中心最多扩展 O(n) 次。

  • 空间复杂度:O(1)。只需常数级别的额外空间,无需存储反转字符串。

总结与对比

方法 核心关键词 时间复杂度 空间复杂度
反转匹配法 反转、公共子串、索引验证 O(n3) O(n)
中心扩展法 对称性、奇偶中心、双指针扩展 O(n2) O(1)
相关推荐
waoooqwe1 小时前
问卷样本真实吗
大数据·数据库·算法·数据分析
苦瓜打怪兽1 小时前
leetcode 热题100(11. 盛最多水的容器)
python·算法·leetcode
多弗朗皮卡丘1 小时前
C++继承
c++·继承
汉克老师2 小时前
GESP2026年9月认证C++七级( 第三部分编程题(2、括号序列))精讲
c++·gesp·小学生·学c++编程
w_zero_one2 小时前
链表(4)
java·数据结构·算法
吠品2 小时前
GitHub 周榜拆解:决策小模型扎堆上位
c语言·开发语言·算法
Ivanqhz2 小时前
MLA、DSA、CSA、HCA
人工智能·算法·机器学习
嘎嘎风3 小时前
MiniMind 学习笔记之 07 模型怎么学会猜词(旋钮是怎么被拧动的)
算法·源码阅读
和裕3 小时前
定制纸箱刀模费全解析:费用定义与可减免合作场景
大数据·运维·网络·人工智能·算法