leetcode5[Longest Palindromic Substring]

最長迴文子串問題,題目描述:給定一個字符串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度爲 1000。

所謂迴文串,就是指一個字符串正序和倒序完全一致,必須"aba","baab"等,本題求的是一個字符串最長的迴文子串,比如"aabbaccddcc"的最長迴文子串就是"ccddcc"。

首先想到的是暴力解法,遍歷每一個字符作爲子串的開端,字符串從後往前的每一個字符作爲子串的結尾,然後再進行迴文串的判斷,因爲要進行三次循環,所以總的時間複雜度爲O(n^{3}),結果超時,但扔然通過93個測試樣例。

暴力法的思路是從兩端向中間找出所有的迴文子串,這樣必然存在大量的重複對比,比如"abdcfdba",a對比了一次,b對比了兩次,d對比了三次,明顯不合理。

優化暴力方法的思路就是動態規劃,動態規劃的核心思想就是大問題化爲小問題來解決 ,假如已知某子串s1爲迴文串,比如"abba",那麼s加上前一位和向後一位的新子串s2爲迴文串的條件就是加的這兩個字符相同,比如"cabbac",描述如下(截圖)。

因此需要一個二維數組來存儲p(i,j)的值 ,依次求出長度爲1到N(字符串長度)的子串是否爲迴文串,其中1和2需要單獨判斷,3到N利用動態方程求得,時間複雜度爲O(n^{2}),缺點是需要額外的空間存儲二維數組,長字符串會有較大開銷,實現代碼如下。

class Solution {
    public String longestPalindrome(String s) {
        int length = s.length();
        Boolean p[][] = new Boolean[length][length];
        int maxlen = 0;
        int start=0,end=0;
        for(int len = 1 ; len <= length ; ++len)
            for(int i = 0;  i< length ; ++i)
            { 
                int j = i+len-1;
                if(j>=length)
                    break;
                p[i][j] = (len==1||len==2||p[i+1][j-1])&&s.charAt(i)==s.charAt(j);
                if(p[i][j]&&len>maxlen)
                {
                    start = i;
                    end = j;
                    maxlen = len;
                }

            }
        return length>1?s.substring(start,end+1):s;

             
    }
}

另一種思路就是從中間向兩端查找,也就是遍歷每一個字符作爲迴文子串的中間點,然後向兩邊對比,這樣的時間複雜度爲O(n^{2})。由於迴文子串的中心可以是一個字符,也可以是兩個字符,所以要分別處理。這種方法也叫做中心擴展法,實現代碼如下。 

class Solution {
    public String longestPalindrome(String s) {
        int length = s.length();
        if(length<2)
            return s;
        int start = 0, end = 0, maxlen = 0;
        for(int i = 0;i < length;++i)
        {
            int lenOdd = expandCenter(s,i, i);
            int lenEven = expandCenter(s,i, i+1);
            int len = Math.max(lenOdd,lenEven);
            if(len>maxlen)
            {
                maxlen = len;
                start = i-(len-1)/2;
                end  = i+len/2;
            }
        }
        return s.substring(start,end+1);
        
             
    }
    public int expandCenter(String s,int L,int R)
    {
        int len = (L==R?-1:0);
        while(L>=0&&R<s.length())
        {
            if(s.charAt(L)!=s.charAt(R))
                break;
            len+=2;
            L--;
            R++;
        }
        return len;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章