文字列から繰り返し文字を削除する

文字列から繰り返し文字を削除する

1. 概要

このチュートリアルでは、文字列から繰り返される文字を削除する方法に関するJavaのいくつかの手法について説明します。

各手法について、we’ll also talk briefly about its time and space complexity.

2. distinctの使用

Java 8で導入されたdistinctメソッドを使用して、文字列から重複を削除することから始めましょう。

以下では、特定の文字列オブジェクトからIntStreamのインスタンスを取得しています。 次に、distinctメソッドを使用して重複を削除します。 最後に、forEachメソッドを呼び出して、個別の文字をループし、それらをStringBuilderに追加します。

StringBuilder sb = new StringBuilder();
str.chars().distinct().forEach(c -> sb.append((char) c));

Time Complexity: O(n) –ループの実行時間は入力文字列のサイズに正比例します

Auxiliary Space:O(n)distinctは内部でLinkedHashSetを使用し、結果の文字列もStringBuilderオブジェクトに格納するため

Maintains Order:はい–LinkedHashSet はその要素の順序を維持するため

そして、Java 8がこのタスクを非常にうまく実行してくれるのは素晴らしいことですが、それを私たち自身の努力と比較してみましょう。

3. indexOfの使用

文字列から重複を削除するための素朴なアプローチには、looping over the input and using the indexOf method to check whether the current character already exists in the resulting stringが含まれます。

StringBuilder sb = new StringBuilder();
int idx;
for (int i = 0; i < str.length(); i++) {
    char c = str.charAt(i);
    idx = str.indexOf(c, i + 1);
    if (idx == -1) {
        sb.append(c);
    }
}

Time Complexity: O(n * n) –各文字について、indexOfメソッドは残りの文字列を実行します

Auxiliary Space:O(n) –結果を格納するためにStringBuilderを使用しているため、線形スペースが必要です

Maintains Order:はい

この方法は、最初のアプローチと同じスペースの複雑さを持っていますが、performs much slower.

4. 文字配列を使用する

converting it into a char array and then looping over each character and comparing it to all subsequent charactersによって文字列から重複を削除することもできます。

以下に示すように、2つのforループを作成し、各要素が文字列内で繰り返されているかどうかを確認しています。 重複が見つかった場合、StringBuilderに追加しません。

char[] chars = str.toCharArray();
StringBuilder sb = new StringBuilder();
boolean repeatedChar;
for (int i = 0; i < chars.length; i++) {
    repeatedChar = false;
    for (int j = i + 1; j < chars.length; j++) {
        if (chars[i] == chars[j]) {
            repeatedChar = true;
            break;
        }
    }
    if (!repeatedChar) {
        sb.append(chars[i]);
    }
}

Time Complexity: O(n * n) –入力文字列をトラバースする内側ループと外側ループがあります

Auxiliary Space:O(n)chars変数は文字列入力の新しいコピーを格納し、StringBuilderを使用して結果を保存するため、線形スペースが必要です

Maintains Order:はい

繰り返しになりますが、2回目の試行はCore Javaオファリングと比較してパフォーマンスが低くなりますが、次の試行でどこに到達するかを見てみましょう。

5. 並べ替えの使用

または、入力文字列をソートして重複をグループ化することにより、繰り返される文字を削除できます。 In order to do that, we have to convert the string to a char array and sort it using the Arrays.sort method. Finally, we’ll iterate over the sorted char array.

すべての反復中に、配列の各要素を前の要素と比較します。 要素が異なる場合は、現在の文字をStringBuilder:に追加します

StringBuilder sb = new StringBuilder();
if(!str.isEmpty()) {
    char[] chars = str.toCharArray();
    Arrays.sort(chars);

    sb.append(chars[0]);
    for (int i = 1; i < chars.length; i++) {
        if (chars[i] != chars[i - 1]) {
            sb.append(chars[i]);
        }
    }
}

Time Complexity: O(n log n) –ソートはdual-pivot Quicksortを使用し、多くのデータセットでO(n log n)パフォーマンスを提供します

Auxiliary Space:O(n)toCharArrayメソッドは入力Stringのコピーを作成するため

Maintains Order:いいえ

最後の試みでもう一度試してみましょう。

6. Setの使用

文字列から繰り返される文字を削除するもう1つの方法は、Setを使用することです。 If we do not care about the order of characters in our output string we can use a HashSet.Otherwise, we can use a LinkedHashSet to maintain the insertion order.

どちらの場合も、入力文字列をループして、各文字をSetに追加します。 文字がセットに挿入されたら、それを繰り返してStringBuilder に追加し、結果の文字列を返します。

StringBuilder sb = new StringBuilder();
Set linkedHashSet = new LinkedHashSet<>();

for (int i = 0; i < str.length(); i++) {
    linkedHashSet.add(str.charAt(i));
}

for (Character c : linkedHashSet) {
    sb.append(c);
}

Time Complexity: O(n) –ループの実行時間は入力文字列のサイズに正比例します

Auxiliary Space:O(n)Setに必要なスペースは、入力文字列のサイズによって異なります。また、結果を保存するためにStringBuilderを使用しています

Maintains Order:LinkedHashSet – はい、HashSet –いいえ

そして今、私たちはコアJavaアプローチと一致しました! これがdistinctがすでに行っていることと非常に似ていることを知っても、それほどショックではありません。

7. 結論

In this article, we covered a few ways to remove repeated characters from a string in Java.これらの各メソッドの時間とスペースの複雑さも調べました。

いつものように、コードスニペットはover on GitHubで見つけることができます。