5.Longest Palindromic Substring

给定一个字符串,求字符串中最长的回文子串。
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

思路:
一、暴力解决,O(n^3) 的时间复杂度,最外层循环为 子串的起始位置,第二层循环为,对字符串中的字符遍历,若与子串的第一个字符相等,则停下来验证这一个子串是否是回文,第里层循环为回文验证。由于“bb……bb”这种字符串,第一次遍历后就得到了结果,不需要再进寻找,所以,需要对程序剪枝,尽量减小时间复杂度。虽然能AC,但时间复杂度还是太高了

string longestPalindrome(string s) {
    string res = "" , tmp = "";
    for (int l = 0; l < (int)s.size(); l++) { //子串起始位置
        for (int i = l; i < (int)s.size(); i++) { //字符串遍历
            if (s[i] == s[l]) {
                tmp = s.substr(l, i - l + 1);
                int tmp_size = tmp.size(), flag = 1;
                for (int j = 0; j < tmp_size/2; j++) { //回文判断
                    if (tmp[j] != tmp[tmp_size - 1 - j]) {
                        flag = 0;
                        break;
                    }
                }
                if (flag) res = tmp.size() > res.size() ? tmp : res;//更新结果
            }
        }
        if ((int)res.size() >= (int)(s.size() - l)) break;//剪枝
    }
    return res;
 }

 

二、从中间往两边扩,时间复杂度O( n^2 ),但是要注意回文个数为奇数个、偶数个,偶数个的话必然中间至少有两个是相等的,比如 noon 中间的 oo相等,而奇数个的话,比如 aba ,可以不管 'b',下标l和r = b的下标,直接对比左边 l-1和右边 r+1的字符是否相等。所以,在处理偶数个时,将 oo 视为一个 O ,即:这儿需要保持 l 不变,将 r 向右移,noon可以看成  nOn,,然后当做奇数处理。

string longestPalindrome(string s) {
    if (s.size() < 2) return s;
    string res = "";
    int n = s.size();
    for (int i = 0; i < n;) {
        int l = i, r = i;
        while (r < n - 1 && s[r] == s[r + 1]) r++;//处理偶数个,r右移
        i = r + 1;
        while (r < n - 1 && l>0 && s[r + 1] == s[l - 1]) {//处理奇数个
            l--;
            r++;
        }
        if ((int)res.size() < r - l + 1) res = s.substr(l, r - l + 1);
    }
    return res;
 }

 

Java 版:

class Solution {
    public String longestPalindrome(String s) {
        String res = "";
        for(int l = 0; l < s.length(); l++){
            for(int i = l; i < s.length(); i++){
                if(s.charAt(l) != s.charAt(i)) continue;
                String tmp = s.substring(l,i+1);
                int n = tmp.length(), flag = 1;
                for(int j = 0; j < n/2; j++){
                    if(tmp.charAt(j) != tmp.charAt(n-1-j)){
                        flag = 0;
                        break;
                    }
                }
                if(flag == 1) res = tmp.length() > res.length() ? tmp : res;
            }
            if(res.length() > s.length() - l) return res;
        }
        return res;
    }
}

 

第二种解法:

  • 使用中间向两边扩的思想;
  • 遇到 "baaaab" 这种情况,先跳过中间的 "aaaa",将 right指针移到最后一个 a 的下标,而 left 处于第一个 a 的下标,此时,开始 left、right 向两边扩,当 s.charAt(left) != s.charAt(right) 时,结束一轮循环;
  • 遍历完字符串 s 后,选择最长的一个作为答案。

class Solution {
    public String longestPalindrome(String s) {
        char[] ch = s.toCharArray();
        String res = "";
        int left, right, n = ch.length;
        for(int i = 0; i < n; ){
            left = i; right = i;
            while(right < n - 1 && ch[right] == ch[right+1]) right++; // 跳过相同的字符
            i = right + 1 ; //下一次开始遍历的位置
            while(left > 0 && right < n - 1 && ch[left-1] == ch[right+1]){ //注意处理边界,0 和 n-1
                left--; //中间像两边扩
                right++;
            }
            if(res.length() < right-left+1) res = s.substring(left, right+1);
        }
        return res;
    }
}

 

posted @ 2020-05-15 20:42  星海寻梦233  阅读(198)  评论(0编辑  收藏  举报