LeetCode最長の回文部分文字列(5つの質問)

LeetCode最長の回文部分文字列

@author:Jingdai
@date:2020.11.13

トピックの説明(5つの質問)

文字列sを指定してs、最長の部分文字列の回文を検索しますs最大長は1000と想定できます。

  • サンプル入力

    "babad"
    
  • サンプル出力

    "bab"
    
  • 注:「aba」も有効な答えです。

アイデアとコード

  • 動的計画法

    まず、動的計画法でこの問題を解決する方法を見てください。動的計画法にとって最も重要なことは、状態遷移方程式を見つけることです。文字列の場合、回文の場合は、その前後の1文字を(境界の問題を考慮せずに)削除しても、それでも回文です。つまりs[i]-s[j]、パリンドロームシーケンスの場合s[i+1]-s[j-1]もパリンドロームシーケンスです。逆にs[i]-s[j]、パリンドロームシーケンスが必要な場合s[i]s[j]同等であり、パリンドロームシーケンスである必要がありs[i+1]-s[j-1]ます。

    ここで、二次元アレイを有するisPalindromeサブストリングが、パリンドロームで表すisPalindrome[i][j]ようにtrue代表s[i]-s[j]パリンドロームストリング。その場合、状態遷移方程式は次のようになります。

    ここに画像の説明を挿入します

    初期条件もすぐに利用できます。それはij等しくisPalindrome[i][j]なければならないときtrueです。

    ここで注意すべき点は越え問題の順序は、ということであるisPalindrome[i][j]必要性は、計算に使用するisPalindrome[i+1][j-1]ことは、結果をisPalindrome[i+1][j-1]最初に横断する必要があり、isPalindrome[i+1][j-1]中にisPalindrome[i][j]左下の位置、それが使用する権利1に左、上から下へ線ではないトラバースラインは、することができますここでトラバース。

    以下は特定のコードです。

    public String longestPalindrome(String s) {
           
           
            
        if (s == null || s.length() == 0)
            return null;
    
        if (s.length() == 1)
            return s; 
    
        char[] chars = s.toCharArray();
        int len = s.length();
        boolean[][] isPalindrome = new boolean[len][len];
    
        for (int i = 0; i < len; i++) {
           
           
            isPalindrome[i][i] = true;
        }
    
        int longestLen = 1;
        int start = 0;
        int end = 0;
    
        for (int j = 1; j < len; j++) {
           
           
            for (int i = 0; i < j; i++) {
           
           
                if (j == i+1) {
           
           
                    isPalindrome[i][j] = chars[i] == chars[j];
                } else {
           
           
                    isPalindrome[i][j] = isPalindrome[i+1][j-1] 
                        && chars[i] == chars[j];
                }
    
                if (isPalindrome[i][j] && j-i+1 > longestLen) {
           
           
                    longestLen = j-i+1;
                    start = i;
                    end = j;
                }
    
            }
        }
    
        return s.substring(start, end+1);
    }
    
  • 中心拡散法

    中心拡散法はその名の通り、各中心の回文の長さを求め、その長さから最長の戻りを見つける必要があります。

    ここに画像の説明を挿入します

    図に示すように、中心には2つの選択肢があり、1つは要素自体であり、もう1つは2つの要素間のギャップです。ここで我々が使用leftし、right2つの変数が表す場合leftright等しく、素子自体の代表である場合right=left+1、中心は二つの要素の間隔を表します。

    中心を選択した後、各中心について、両側の文字が等しい場合は、中央の回文の長さに2を追加します。それ以外の場合は、直接戻ります。文字列全体のすべての中心をトラバースして、最大の長さを見つけて戻ります。

    ここで注意すべきことの1つは、2つのセンターによって選択されたパリンドローム文字列の初期値が異なることです。コードを作成するときに判断する必要があります。

    以下は特定のコードです。

    public String longestPalindrome(String s) {
           
           
            
        if (s == null || s.length() == 0)
            return null;
    
        if (s.length() == 1)
            return s;
    
        char[] chars = s.toCharArray();
        int start = 0;
        int end = 0;
        int longestLen = 1;
    
        int tempOddLen = 0;
        int tempEvenLen = 0;
        int tempMaxLen = 0;
        for (int i = 0; i < chars.length - 1; i++) {
           
           
            tempOddLen = palindromeLength(chars, i, i);
            tempEvenLen = palindromeLength(chars, i, i+1);
            tempMaxLen = tempOddLen > tempEvenLen ? tempOddLen : tempEvenLen;
            if (tempMaxLen > longestLen) {
           
           
                longestLen = tempMaxLen;
                start = i - (longestLen - 1) / 2;
                end = start + longestLen - 1;
            }
        }
    
        return s.substring(start, end+1);
    
    }
    
    public int palindromeLength(char[] s, int left, int right) {
           
           
    
        int len = 0;
        if (left == right)
            len = -1;
    
        while (left >=0 && right <= s.length - 1 && s[left] == s[right]) {
           
           
            left--;
            right++;
            len += 2;
        }
        return len;
    }
    

おすすめ

転載: blog.csdn.net/qq_41512783/article/details/109682624