LeetCode 5. 最长回文子串——中心扩展法彻底讲透

LeetCode 5. 最长回文子串——中心扩展法彻底讲透

一、题目描述

给定一个字符串 s,找到其中最长的回文子串,并返回这个子串。

示例:

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

二、什么是回文串?

回文串(Palindrome):

正着读和反着读完全一样的字符串。

例如:

"a"
"aa"
"aba"
"abba"
"racecar"

都属于回文串。

而:

"ab"
"abc"
"abca"

不是回文串。


三、回文的核心性质:左右对称

所有回文串一定存在一个「对称中心」。

例如:

奇数长度回文

aba

a ← b → a

中心是:

b

偶数长度回文

abba

ab ← → ba

中心是:

两个字符之间的缝隙

因此:

只要找到所有可能的对称中心,然后不断向两边扩散,就能找到所有回文串。

这就是中心扩展法。


四、整体思路

对于字符串中的每一个位置 i

我们都尝试两种情况:

情况1:奇数回文

expand(i, i)

例如:

aba
 ^

情况2:偶数回文

expand(i, i + 1)

例如:

abba
  ^^

每次扩散结束后:

记录当前回文的长度。

如果比之前最长的回文还长:

就更新答案。


五、扩散函数怎么写?

定义函数:

expand(left, right)

表示:

leftright 开始向两边扩散。


扩散条件

三个条件必须同时满足:

left >= 0
right < len(s)
s[left] == s[right]

满足条件:

left -= 1
right += 1

继续扩散。


为什么最后要回退?

例如:

aba

扩散过程:

left=1 right=1

↓

left=0 right=2

↓

left=-1 right=3

退出循环时:

left=-1
right=3

已经越界了。

真正有效的边界应该是:

0 ~ 2

因此返回:

left + 1
right - 1

六、完整代码

class Solution:
    def longestPalindrome(self, s: str) -> str:
        # 长度小于2直接返回
        if len(s) < 2:
            return s

        start = 0
        end = 0

        def expand(left, right):
            while (
                left >= 0
                and right < len(s)
                and s[left] == s[right]
            ):
                left -= 1
                right += 1

            return left + 1, right - 1

        for i in range(len(s)):

            # 奇数长度回文
            l1, r1 = expand(i, i)

            # 偶数长度回文
            l2, r2 = expand(i, i + 1)

            # 更新最长奇数回文
            if r1 - l1 > end - start:
                start = l1
                end = r1

            # 更新最长偶数回文
            if r2 - l2 > end - start:
                start = l2
                end = r2

        return s[start:end + 1]

七、拿示例跑一遍

字符串:

s = "babad"

i = 0

奇数:

b

长度:

1

偶数:

最长:

b

i = 1

奇数:

bab

长度:

3

更新答案:

bab

偶数:


i = 2

奇数:

aba

长度:

3

和当前最长相同。

保持:

bab

最终返回:

bab

八、为什么 i + 1 不会越界?

假设:

s = "abc"

最后一次:

i = 2
expand(2, 3)

进入函数:

right < len(s)

即:

3 < 3

不成立。

直接退出。

不会报错。


九、复杂度分析

时间复杂度

O(n²)

共有:

2n 个中心

每个中心最多扩散:

O(n)

因此:

O(n²)

空间复杂度

O(1)

只使用有限几个变量。


十、高频易错点

1、只处理奇数回文

错误:

expand(i, i)

遗漏:

expand(i, i + 1)

会导致:

"cbbd"

输出错误。


2、扩散使用 if

错误:

if s[left] == s[right]:

只能扩一层。

必须使用:

while

持续扩散。


3、忘记回退边界

错误:

return left, right

应该:

return left + 1, right - 1

4、长度公式少写 +1

错误:

right - left

正确:

right - left + 1

5、字符串切片忘记 +1

错误:

s[start:end]

正确:

s[start:end + 1]

因为 Python 切片:

左闭右开

十一、一句话总结

最长回文子串的核心思想:

枚举每一个可能的回文中心,从中心向两边不断扩散,记录最长回文的左右边界。

记忆口诀:

一个字符找奇数,
两个字符找偶数;
左右不断往外扩,
记录最长回文串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值