1. 程式人生 > 實用技巧 >akka stream第三課-模組化

akka stream第三課-模組化

LeetCode 5 最長迴文子串

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

動態規劃

執行用時:209 ms, 在所有 Java 提交中擊敗了12.42%的使用者
記憶體消耗:50.1 MB, 在所有 Java 提交中擊敗了5.01%的使用者

class Solution{
    //動態規劃
    //dp[i][j]表示str[i, j]範圍內最長迴文子串長度, j>=i
    //dp[i][j]與dp[i+1][j]、dp[i][j-1]、dp[i+1][j-1]有關
    //1. 若str[i]==str[j] and dp[i+1][j-1]==j-(i+1)
    //      dp[i][j] = dp[i+1][j-1]+2
    //2. 其它情況
    //      dp[i][j] = max{dp[i+1][j], dp[i][j-1], dp[i+1][j-1]}
    //初始: dp[i][i] = 1
    public String longestPalindrome(String s) {
        if(s==null || s.length()<=1) {
            return s;
        }

        int[][] dp = new int[s.length()][s.length()];
        //狀態初始化
        for(int i=0; i<s.length(); i++) {
            dp[i][i] = 1;
        }
        //狀態遞推O(N2)
        int left = 0, right = 0;
        //遍歷方式存在問題(保證後有效性)
        for(int j=0; j<s.length(); j++) {
            for(int i=0; i<=j; i++) {
                if(i==j) {
                    continue;
                }
                //考慮奇對稱、偶對稱兩種情況下的初始情況(兩個值、三個值)
                if(s.charAt(i)==s.charAt(j) 
                && (i+1==j || dp[i+1][j-1]==(j-i-1))) {
                    dp[i][j] = j+1-i;
                }
                else {
                    dp[i][j] = Math.max(
                        i+1==j? 0: dp[i+1][j-1], 
                        Math.max(dp[i+1][j], dp[i][j-1])
                    );
                }
                //記錄字串起始座標
                if(right+1-left < dp[i][j] && dp[i][j]==j+1-i) {
                    left = i;
                    right = j;
                }
            }
        }
        return s.substring(left, right+1);
    }
}

暴力優化: 中心擴散

執行用時:58 ms, 在所有 Java 提交中擊敗了59.81%的使用者
記憶體消耗:37.6 MB, 在所有 Java 提交中擊敗了67.40%的使用者

//問題描述:在給定字串中找到最長的迴文“子串”,迴文子串的定義為:字串對稱分佈,即從左到右、從右到左遍歷輸出一致
/**動態規劃:
 * 狀態轉移:Sub[i,j]表示arr[i]..arr[j]組成的子串
 *          若Sub[i,j]是迴文串,則需要滿足:Sub[i+1,j-1]是迴文串,且arr[i] == arr[j]
 * 遞推:找到一個最小的迴文串,例如"aa"、"aba",由該回文串向外擴充套件
 * */
 //O(N2/2)
class Solution{
    public String longestPalindrome(String s) {
        if(s.length()<=1) return s;
        if(s.length()==2) return (s.charAt(0)==s.charAt(1))?s:s.charAt(0)+"";

        int maxLen = 1, minLeft = 0, maxRight = 0;
        //1、找到一個最小的迴文串(由第二個向倒數第二個尋找)
        //2、由最小回文串向兩邊擴充套件,找到一個最長的迴文串
        //時間複雜度:O(N2)
        for(int i=1;i<s.length()-1;i++){
            //偶數
            if(s.charAt(i)==s.charAt(i-1)){
                int currLen = searchPalindrome(s, i-1, i);
                if(maxLen < currLen){
                    maxLen = currLen;
                    minLeft = i - currLen/2;
                    maxRight = i-1 + currLen/2;
                }
            }
            if(s.charAt(i) == s.charAt(i+1)){
                int currLen = searchPalindrome(s, i, i+1);
                if(maxLen < currLen){
                    maxLen = currLen;
                    minLeft = i+1 - currLen/2;
                    maxRight = i + currLen/2;
                }
            }
            //奇數
            if(s.charAt(i-1)==s.charAt(i+1)){
                int currLen = searchPalindrome(s, i-1, i+1);
                if(maxLen < currLen){
                    maxLen = currLen;
                    minLeft = i - currLen/2;
                    maxRight = i + currLen/2;
                }
            }
        }

        System.out.println("maxLen="+maxLen);
        return s.substring(minLeft, maxRight+1);
    }

    public int searchPalindrome(String s, int i, int j){
        int maxLen = j-i+1;
        i--;j++;
        while(i>=0 && j<s.length()){
            if(s.charAt(i) != s.charAt(j)) break;
            maxLen += 2;
            i--;j++;
        }
        return maxLen;
    }

}