1. 程式人生 > 其它 >LeetCode No5 最長迴文子串

LeetCode No5 最長迴文子串

題目

給你一個字串 s,找到 s 中最長的迴文子串。

示例 1:

輸入:s = "babad"
輸出:"bab"
解釋:"aba" 同樣是符合題意的答案。

示例 2:

輸入:s = "cbbd"
輸出:"bb"

提示:

1 <= s.length <= 1000
s 僅由數字和英文字母組成

解題思路

中心擴充套件法

首先要知道迴文串的定義,迴文串是一個正讀和反讀都一樣的字串,比如 aba 或者 abba,既然正讀與反讀都是一樣,那麼這個串必然有一箇中心對稱點,我們可以利用這個中心點向兩邊擴充套件,找出最大的迴文字串。遍歷字元,把當前下標作為中心點,向兩邊進行擴充套件,直到左邊的字元和右邊的字元不一樣,當然,就像給出的樣例一樣,迴文串有可能是偶數個數也有可能是奇數個數,所以要以偶數迴文串以及奇數迴文串為目標求兩個迴文串,然後再取較大的那個。遍歷完陣列後,我們就可以得到最大回文字串了。

動態規劃

這種迴文字串的題目是DP裡面的經典題目了,遞推式也很簡單,我們定義dp[len][len]陣列,dp[i][j]=true表示從下標i至下標j的字串是迴文串,而如果想要dp[i][j]為迴文串,則必須要滿足dp[i+1]dp[j-1]=true && s[i]==s[j]
同樣我們再考慮下邊界的情況,如果i至j,只有一個字元或者只有兩個字元並且兩個字元相等的時候,這個時候就找到了邊界條件,也就可以完成這個DP了。

AC程式碼

中心擴充套件法

點選檢視程式碼
class Solution {
    private String getStr(String s, int low, int high) {
        int len = s.length();
        while( low>=0 && high<len ) {
            if( s.charAt(low)==s.charAt(high) ) {
                low --;
                high ++;
            } else {
                break;
            }
        }
        return s.substring(low+1, high);
    }

    public String longestPalindrome(String s) {
        int len = s.length();
        if( len<2 ) {
            return s;
        }
        String res = "";
        for(int i=0; i<len-1; i++) {
            String odd = getStr(s, i, i);
            String even = getStr(s, i, i+1);
            String maxStr = odd.length()>even.length()?odd:even;
            if( maxStr.length() > res.length() ) {
                res = maxStr;
            }
        }
        return res;
    }
}

動態規劃

點選檢視程式碼
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        // 空串和只有一個字元的字串可以直接返回
        if( len < 2 ) {
            return s;
        }
        String res = s.substring(0, 1);
        boolean dp[][] = new boolean[len][len];
        for(int i=0; i<len; i++) {
            dp[i][i] = true;
        }
        char[] chars = s.toCharArray();
        // 列舉最長迴文串的長度
        for(int k=2; k<=len; k++) {
            for(int i=0; i<len; i++) {
                int j = k + i - 1;
                if( j>=len ) {
                    break;
                }
                if( chars[i]!=chars[j] ){
                    dp[i][j] = false;
                    continue;
                }
                if( j-i<=2 ) {
                    dp[i][j] = true;
                } else {
                    dp[i][j] = dp[i+1][j-1];
                }
                if( dp[i][j] && res.length()<j-i+1 ) {
                    res = s.substring(i, j+1);
                }
            }
        }
        return res;
    }
}