【LeetCode-字符串】最长回文子串

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

输入: "cbbd"
输出: "bb"

题目链接: https://leetcode-cn.com/problems/longest-palindromic-substring/

思路1

暴力法。求出所有的子串,然后判断子串是否是回文串,保留最长的回文串。代码如下:

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty()) return "";
        if(s.length()==1) return s;

        string ans = "";
        for(int i=0; i<s.length(); i++){
            for(int j=0; j<=s.length()-i; j++){
                string ss = s.substr(i,j);
                if(ss.length()>ans.length() && isOk(ss)){
                    ans = ss;
                }
            }
        }
        return ans;
    }

    bool isOk(string s){
        int left=0;
        int right=s.length()-1;
        while(left<right){
            if(s[left]!=s[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};
  • 时间复杂度:O(n^3)
    外面两层循环,中间的substr应该也要O(n)(没搜到substr的时间复杂度),所以为O(n^3)。
  • 空间复杂度:O(1)

该方法超时未通过。

思路2

如果一个字符串是回文串,那么从该字符串中心开始左右是对称的。所以,我们可以遍历字符串,当遍历到某个字符时,设置两个指针,以该字符为中心向左右扩展,并统计左右两边相等的字符个数,也就是回文串的长度。需要注意的是,当字符串长度为奇数时,如aba,则两个指针都从b开始扩展即可;如果字符串长度为偶数,如abba,这样如果两个指针都从同一位置开始则找不到回文串,尽管该字符串就是一个回文串。为了避免这个问题,对于每个字符我们要左右扩展两次:第一次左右指针从同一位置出发,第二次右指针从左指针的下一个位置出发(i和i+1)。代码如下:

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty()) return "";
        if(s.length()==1) return s;

        int maxLen = -1;
        string ans = "";
        int start=0, end=0;
        for(int i=0; i<s.length(); i++){
            int len1 = spanAroundCenter(s, i, i);
            int len2 = spanAroundCenter(s, i, i+1);
            int len = max(len1, len2);
            if(len>maxLen){
                maxLen = len;
                if(len2>len1){
                    start = i-len/2+1;    // 注意这个
                    end = i+len/2;
                }else{
                    start = i-len/2;
                    end = i+len/2;
                }
            }
        }
        return s.substr(start, end-start+1);
    }

    int spanAroundCenter(string s, int left, int right){
        int len = 0;
        while(left>=0 && right<s.length()){
            if(s[left]==s[right]){
                len++;
            } else return right-left-1; // 不能直接返回len,直接返回len无法区别是哪种扩展方式
            left--;
            right++;
        }
        return right-left-1;
    }
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

猜你喜欢

转载自www.cnblogs.com/flix/p/12692867.html