每天一道演算法題:最長迴文子串

glmapper發表於2018-03-11

##題目 給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 長度最長為1000。

示例:

輸入: "babad"

輸出: "bab"

注意: "aba"也是有效答案
複製程式碼

示例:

輸入: "cbbd"

輸出: "bb"
複製程式碼

思路

一開始是想用最笨的方法來解的,也就是找出所有的字串,然後再對所有的子串進行迴文檢測,並記錄長度。這種方式時間複雜度可想而知,O(n)*O(n)*O(n)=O(n^3)。所以這種肯定是不能滿足我們要求的。

ok,那我們來分析一下這個問題,先把這個問題特殊化;

  • 假如輸入的字串長度就是1

    那麼這個字串的最長迴文串就是它自己,長度就是1

  • 假如字串長度為2,它要是迴文串的化,就需要兩個字元是相等的。

    即:s[i] == s[j] 且i-j=1(此處假定i是較大索引位置)

  • 那麼對於i-j>1的情況下呢?是不是隻要滿足下面的條件就可以了:

    即:s[i] == s[j]&&s[i-1] == s[j+1]

其實這種思路就是動態規劃。關於動態規劃的理論性文字就不碼了,有興趣的小夥伴闊以自行學習。下面就針對這個問題碼一下程式碼:

public String longestPalindrome(String s) {
    //  長度為1,返回當前串
    if (s.length()==1){
        return s;
    }
    //長度為2並且兩個字元相等則返回
    if (s.length()==2&&s.charAt(0)==s.charAt(1)){
        return s;
    }
    //用於標記isLongestPalindrome[j][i]即從j到i是否是迴文串;
    //如isLongestPalindrome[1][5]==true則表示字串索引位置從1到5的子串是迴文串。
    boolean[][] isLongestPalindrome = new boolean[s.length()][s.length()];
    //最長迴文串初始最大為0
    int maxlen = 0;
    //對應的maxlen的開始索引位置
    int beginIndex = 0;
    //對應的maxlen的結束索引位置
    int lastIndex = 0;
    for (int i=0;i<s.length();i++){
        int j=i;
        while(j>=0){
            //滿足上述的第三個條件,即當前s.charAt(i)==s.charAt(j)並
            //且s[j+1到i-1]也是迴文串
            if (s.charAt(i)==s.charAt(j)&&(i-j<2||isLongestPalindrome[j+1][i-1])){
                isLongestPalindrome[j][i]=true;
                if (maxlen < i-j+1) {
                    beginIndex = j;
                    lastIndex = i+1;
                    maxlen = i-j+1;
                }
            }
            j--;
        }
    }

    return s.substring(beginIndex,lastIndex);
}
複製程式碼

相關文章