LeetCode5、最長のテキスト文字列

タイトル説明

https://leetcode-cn.com/problems/longest-palindromic-substring/
ここに画像の説明を挿入

解決策(既存の問題-dp配列トラバーサルの順序はまだ明確ではありません)

初めてコードを渡す:

class Solution {
    
    
    public String longestPalindrome(String s) {
    
    
        //字符串,使用双指针,则使用二维数组
        if(s==null) return null;
        if(s.length()==0) return null;
        if(s.length()==1) return s;
        int[][]dp = new int[s.length()][s.length()];

        //边界初始化
        for(int i=0;i<s.length();i++){
    
    
            for(int j=0;j<s.length();j++){
    
    
                if(i>j)
                    dp[i][j] = 0;
                else if(i==j)
                    dp[i][j] = 1;
            }
        }
        int max = 0;
        //递推
        for(int i=s.length()-1;i>=0;i--){
    
    
            for(int j=s.length()-1;j>=0;j--){
    
    
                if(i<j){
    
    
                    if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
    
    
                        dp[i][j] = j-i+1;//当前的字符串就是一个回文串

                    }else
                    dp[i][j] = Math.max(
                            dp[i+1][j],Math.max(1,//注意,可能是1最大了
                            dp[i][j-1])
                        );
                }
                if(max<dp[i][j]){
    
    
                    max = dp[i][j];
                }
                
            }
        }
        if(max==1) return s.substring(0,1);
       // System.out.println(dp[0][s.length()-1]+" "+max);
        //在dp数组里面找到和dp[0][s.length()-1]相等的值,那么它就是此时的最长回文字串
        for(int i=0;i<s.length();i++){
    
    
            for(int j=0;j<s.length();j++){
    
    
                if(i<j && dp[i][j]==j-i+1 && dp[i][j]==max){
    
    //必须是该字串
                    //System.out.println(dp[0][s.length()-1]+" "+max+" "+i+" "+j);
                    return s.substring(i,j+1);
                }
            }
        }//找不到,则不存在
        return null;

    }
}

ここに画像の説明を挿入
2回目:

class Solution {
    
    
    public String longestPalindrome(String s) {
    
    
        //字符串,使用双指针,则使用二维数组
        if(s==null) return null;
        if(s.length()==0) return null;
        if(s.length()==1) return s;
        int[][]dp = new int[s.length()][s.length()];

        //边界初始化
        int max = 0;
        //递推
        for(int i=s.length()-1;i>=0;i--){
    
    
            for(int j=s.length()-1;j>=0;j--){
    
    
                if(i>j)
                    dp[i][j] = 0;
                else if(i==j){
    
    
                    dp[i][j] = 1;
                }else{
    
    
                    if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
    
    
                        dp[i][j] = j-i+1;//当前的字符串就是一个回文串

                    }else
                    dp[i][j] = Math.max(
                            dp[i+1][j],Math.max(1,//注意,可能是1最大了
                            dp[i][j-1])
                        );
                }
                if(max<dp[i][j]){
    
    
                    max = dp[i][j];
                }
                
            }
        }
        //if(max==1) return s.substring(0,1);
       // System.out.println(dp[0][s.length()-1]+" "+max);
        //在dp数组里面找到和dp[0][s.length()-1]相等的值,那么它就是此时的最长回文字串
        for(int i=0;i<s.length();i++){
    
    
            for(int j=0;j<s.length();j++){
    
    
                
                if(i<=j && dp[i][j]==j-i+1 && dp[i][j]==max){
    
    //必须是该字串
                    //System.out.println(dp[0][s.length()-1]+" "+max+" "+i+" "+j);
                    return s.substring(i,j+1);
                }
            }
        }//找不到,则不存在
        return null;

    }
}

ここに画像の説明を挿入

3回目:

class Solution {
    
    
    public String longestPalindrome(String s) {
    
    
        //字符串,使用双指针,则使用二维数组
        if(s==null) return null;
        if(s.length()==0) return null;
        if(s.length()==1) return s;
        int[][]dp = new int[s.length()][s.length()];

        //边界初始化
        int max = 0;
        int start=0,end=0;
        //递推
        for(int i=s.length()-1;i>=0;i--){
    
    
            for(int j=s.length()-1;j>=0;j--){
    
    
                if(i>j)
                    dp[i][j] = 0;
                else if(i==j){
    
    
                    dp[i][j] = 1;
                }else{
    
    
                    if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
    
    
                        dp[i][j] = j-i+1;//当前的字符串就是一个回文串
                        if(dp[i][j]>max){
    
    
                            start = i;
                            end = j;
                        }

                    }else
                    dp[i][j] = Math.max(
                            dp[i+1][j],Math.max(1,//注意,可能是1最大了
                            dp[i][j-1])
                        );
                }
                if(max<dp[i][j]){
    
    
                    max = dp[i][j];
                }
                
            }
        }
        return s.substring(start,end+1);
        

    }
}

ここに画像の説明を挿入
4回目:

class Solution {
    
    
    public String longestPalindrome(String s) {
    
    
        //字符串,使用双指针,则使用二维数组
        if(s==null) return null;
        if(s.length()==0) return "";
        if(s.length()==1) return s;
        int[][]dp = new int[s.length()][s.length()];

        //边界初始化
        int max = 1;//最大值起码等于1
        int start=0,end=0;
        //递推
        for(int i=s.length()-1;i>=0;i--){
    
    
            for(int j=s.length()-1;j>=0;j--){
    
    
                if(i>j)
                    dp[i][j] = 0;
                else if(i==j){
    
    
                    dp[i][j] = 1;
                }else{
    
    
                    if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
    
    //之前的dp[i+1][j-1]本身就是回文串
                        dp[i][j] = j-i+1;//当前的字符串就是一个回文串,一定会有一个dp[i][j]会进到这里
                        if(dp[i][j]>max){
    
    //只要进到这里,整体是回文串
                            start = i;
                            end = j;
                            max = dp[i][j];
                        }

                    }else//这里因为i<j,所以i+1<=j,dp[i+1][j]>=1,所以我们去掉了比较1
                    dp[i][j] = dp[i+1][j]>dp[i][j-1]?dp[i+1][j]:dp[i][j-1];
                    
                }
               
                
            }
        }
        return s.substring(start,end+1);
        

    }
}

ここに画像の説明を挿入

問題があったことがわかりました:
コードテストに合格しましたが、

dp配列で理由がわかりません。最終的な計算結果dp [0] [s.length()-1]がmaxと等しくない場合があります。dp[i] [j]をs [iを意味するように明確に定義しました。 …j]最長の回文ストリング。
ここに画像の説明を挿入

最後に、アイデアのデバッグに時間を費やし、問題を見つけました。
つまり、dp [i] [j-1]が計算されていない場合、それを使用して再帰的にdp [i] [j]を実行したので、j次元のトラバーサル方向が間違っているため、dp [0] [s.length()-1]は必ずしもmaxに等しくありません。しかし、なぜそれがテストに合格できるのか興味があります。

変更されたコード:

class Solution {
    
    
    public String longestPalindrome(String s) {
    
    
        //字符串,使用双指针,则使用二维数组
        if(s==null) return null;
        if(s.length()==0) return "";
        if(s.length()==1) return s;
        int[][]dp = new int[s.length()][s.length()];//dp[i][j]定义为从s[i..j]的最长回文串

        //边界初始化
        int max = 1;//最大值起码等于1
        int start=0,end=0;
        //递推
        for(int i=s.length()-1;i>=0;i--){
    
    //从图上可视化看出应该使用后序遍历
            for(int j=0;j<s.length();j++){
    
    
                if(i>j)
                    dp[i][j] = 0;
                else if(i==j){
    
    
                    dp[i][j] = 1;
                }else{
    
    
                    if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]== j-i-1){
    
    //之前的dp[i+1][j-1]本身就是回文串
                        dp[i][j] = j-i+1;//当前的字符串就是一个回文串,一定会有一个dp[i][j]会进到这里
                        if(dp[i][j]>max){
    
    //只要进到这里,整体是回文串
                            start = i;
                            end = j;
                            max = dp[i][j];
                        }

                    }else//这里因为i<j,所以i+1<=j,dp[i+1][j]>=1,所以我们去掉了比较1
                    dp[i][j] = dp[i+1][j]>dp[i][j-1]?dp[i+1][j]:dp[i][j-1];
                    
                }
               
                
            }
        }
        //按理来说dp[0][s.length()-1]表示的是最大值,应该=max
        return s.substring(start,end+1);
        

    }
}

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_44861675/article/details/114497607