5. 最长回文子串-Leetcode刷题(C++) 4种解法

本文详细介绍了如何解决LeetCode上的最长回文子串问题,包括四种C++解法:左右指针法、中心扩散法及其优化、动态规划。通过实例分析和代码展示,阐述每种方法的思路和效率,并提供了执行时间和内存消耗对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目(来源:leetcode):

给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad” – 输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd” – 输出:“bb”
示例 3:
输入:s = “a” – 输出:“a”
示例 4:
输入:s = “ac” – 输出:“a”

二、分析

  1. 通过设定左右指针:start和end指针,移动窗口,然后每次判断子串是否为回文字符串,判断方式为遍历子串的前一半,保证其与子串的后一半对称相等。时间复杂度: O ( n 3 ) O(n^3) O(n3)
  2. 中心扩散法:从每一个位置出发,向两边扩散即可。遇到不是回文的时候结束。举个例子,str = acdbbdaa,我们需要寻找从第一个 b(位置为 3)出发最长回文串为多少。怎么寻找?
    1、首先往左寻找与当期位置相同的字符,直到遇到不相等为止。
    2、然后往右寻找与当期位置相同的字符,直到遇到不相等为止。
    3、最后左右双向扩散,直到左和右不相等。
a c d b b d a a
b 左寻找,直接不相同
b b 由寻找,找到一个b之后不再相同
dbbd //从此开始左右同时找,d = d, a != c,所以结束查找。
所以从b开始寻找的话,最长回文子串是dbbd。
  1. 中心扩散算法的优化,以上算法虽然是 O ( n 2 ) O(n^2) O(n2)时间复杂度,但还有一些优化空间:
a c d b b d a a
当找到第一个b的时候,由于右边还是字符b,那么可以直接跳过,因为执行到下一步循环(也就是第二个b),还要筛到第一个b,他们两个所构成的最长子回文串是一样的。
比如该情况:a c d b b b b b b d a a,这样中间的6个b只遍历其中一个就可以。
equalright 记录了后边第一个不相等字符的下标,当遍历到第一个b(下标3)时:equalright = 9; (d)的下标。
  1. 动态规划
    定义dp[i][j]表示子串 s[i…j] 是否为回文子串,这里子串 s[i…j] 定义为左闭右闭区间,可以取到 s[i] 和 s[j]。
    如果字符串最右侧字符与最左侧字符相等,且中间的子串是回文串,则dp[i][j]是回文串。
例如:A=[a b b a]
求dp[0][3] 即 判断 abba 是否为回文串,通过:A[0] == A[3] && dp[1][2] = true(bb为回文串),得知该字符串为回文串。
所递推关系为:dp[i][j] = (A[i] == A[j]) && dp[i + 1][j - 1]
当然如果j - i <= 1,单个字符 或 连续2个相等字符,一定是回文的。

从这也可以看出来,i 要从大到小遍历,j 要从小到大遍历。

三、代码:

  1. 左右指针
class Solution {
   
   
public:
    string longestPalindrome(string s) {
   
   
        int start(0), end(0), length(0);
        string sresult = s.substr(0,1);
        // 停止条件为start到达原字符串的倒数第一个下标
        for(; start < s.length() -1; end ++){
   
   
       	// 如果en
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值