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

一、题目(来源: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

你可能感兴趣的:(leetcode)