Java トピックのトレーニング - 文字列の反転と共通部分文字列の計算

目次

1.文字列反転

2. 共通部分文字列の計算


1.文字列反転

タイトル説明:

小文字のみを含む文字列を受け取り、その文字列の逆バージョンを出力します。(文字列の長さが 1000 を超えない)

説明を入力してください:

小文字のみを含む文字列である行を入力します。

出力の説明:

この文字列の反転文字列を出力します。

例 1

入力: abcd

出力: DCBA

トピック分析:

        この質問は非常に古典的な質問です。多くの方法があります。ここでは、StringBuilder の文字列 sb を作成することを選択し、最初の文字列を後ろから前にトラバースし、StringBuilder の append メソッドを使用してトラバーサルの順序で要素を追加します。 sb 文字列を返し、文字列反転を実装するのが最善です。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        if(s.length() == 0){
            return;
        }
        System.out.println(res(s));
    }

    public static String res(String s){
        StringBuilder sb = new StringBuilder();
        for (int i = s.length() - 1; i >= 0; i--) {
            sb.append(s.charAt(i));
        }
        return sb.toString();
    }
}

2. 共通部分文字列の計算

タイトル説明:

小文字のみを含む 2 つの文字列が与えられた場合、2 つの文字列の最大の共通部分文字列の長さを計算します。

注: 部分文字列の定義は、文字列からプレフィックスとサフィックスの一部を削除する (または削除しない) ことによって形成される文字列を指します。

データ範囲: 文字列長: 1<=s<=150

高度: 時間複雑度: O( n^{3})、空間複雑度: O(n)

説明を入力してください:

小文字のみを含む 2 つの文字列を入力してください

出力の説明:

最大共通部分文字列の長さを表す整数を出力します

例 1

入力: asdfas

           ウェラスファスワー

出力: 6

トピック分析: 

この考え方は、基本的には最長共通部分文字列を見つける考え方と同じですが、細かい点で異なる点もあります。

以下に 3 つのアイデアを示します。

1. 動的計画法 (推奨)

        (1). 状態配列 arr = new int[s1.length() + 1][s2.length() + 1] を作成します。

        (2). 状態方程式を求めます: この位置の文字が同じ (s1.charAt(i - 1) == s2.charAt(j - 1)) 場合、この時点で文字が繰り返されます。前の状態と直接等しい +1 の結果。

        (3). 初期状態を設定します: デフォルトは 0 で、この質問は条件によって自動的に更新されます。

        タイトルでは最大の共通部分文字列の長さを返す必要があるため、変数 max を設定して最大長を格納し、max を更新して、最後に max を返す必要があります。

2. 一般的な考え方

        2 層のループを設定します。外側のループは部分文字列の開始位置を制御し、内側のループは逆方向にトラバースし、StringBuilder の文字列 sb を作成します (変更は簡単です)。内側のループは逆方向にトラバースし、StringBuilder メソッドを介して文字を追加します。このとき、文字列 s2 に文字列 sb が含まれていれば、sb の長さ (部分文字列) が保存された最大値 max よりも大きいかどうかを判断でき、すべての部分文字列をトラバースした後、at に戻ります。最後。

        ここで、ループの条件と範囲に注意する必要があります。範囲は s1 の制限です。

3. 左右のポインター - 通常の思考の最適化と見なすことができます

        s1の左端から開始するように左ポインタを左に設定し、s1の右端から開始するように右ポインタを右に設定する. アイデアは少し従来のアイデアに似ています. 外側のループは左ポインタの位置を制御します.内側のループで left <= right である限り、このとき傍受された s1 が判断されます. s2 に部分文字列(左, 右) が含まれているかどうか、およびその長さが以前に記録された最長の部分文字列の最大長を超えているかどうかが判断されます.条件を超えていないか満たさない, rright--, トラバースを続ける; 超えている限り, これはそうです (左 = i) 最大長 (右は常に -- であるため), 直接内側のループを終了します(トラバーサルを継続することも s2 に含まれる条件を満たしますが、長さがどんどん短くなっていきます。この時点で最長の部分文字列が見つかったので、継続する必要はありません)。

       タイトルでは最大の共通部分文字列の長さを返す必要があるため、変数 max を設定して最大長を格納し、max を更新して、最後に max を返す必要があります。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s1 = scanner.nextLine();
        String s2 = scanner.nextLine();

        System.out.println(comLen(s1, s2));

    }

    //1. 动态规划
    public static int comLen(String s1, String s2){
        int[][] res = new int[s1.length() + 1][s2.length() + 1];
        res[1][1] = 0;
        int max = 0;
        for (int i = 1; i <= s1.length() ; i++) {
            for (int j = 1; j <= s2.length(); j++) {
                if(s1.charAt(i - 1) == s2.charAt(j - 1)){
                    res[i][j] = res[i - 1][j - 1] + 1;
                    if(max < res[i][j]){
                        max = res[i][j];
                    }
                }
            }
        }
        return max;
    }

    //2. 普通思路
    public static int comLen1(String s1, String s2){
        int max = 0;
        for (int i = 0; i < s1.length(); i++) {
            StringBuilder sb = new StringBuilder();
            for(int j = i; j < s1.length(); j++){
                if(s2.contains(sb.append(s1.charAt(j)))){
                    if(sb.length() > max){
                        max = sb.length();
                    }
                }
            }
        }
        return max;
    }

    //3. 左右指针
    public static int comLen2(String s1, String s2){
        int max = 0;
        for (int i = 0; i < s1.length(); i++) {
            int left = i;
            int right = s1.length();
            while(left <= right){
                int t = s1.substring(left, right).length();
                if(s2.contains(s1.substring(left, right)) && max < t){
                    max = t;
                    break;
                }
                right--;
            }
        }
        return max;
    }
}

提案やアイデアがあれば、一緒に議論して勉強してください〜 

おすすめ

転載: blog.csdn.net/lil_ghost_/article/details/129887230