Удаление повторяющихся символов из строки

Удаление повторяющихся символов из строки

1. обзор

В этом руководстве мы обсудим несколько техник в Java, позволяющих удалить повторяющиеся символы из строки.

Для каждого методаwe’ll also talk briefly about its time and space complexity.

2. Используяdistinct

Начнем с удаления дубликатов из нашей строки с помощью методаdistinct, представленного в Java 8.

Ниже мы получаем экземпляр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.

Как видно ниже, мы создаем два цикла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: Да

Опять же, наша вторая попытка работает плохо по сравнению с предложением 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

Другой способ удалить повторяющиеся символы из строки - использовать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 – Нет

И теперь мы подошли к подходу Core Java! Неудивительно, что это очень похоже на то, что уже делаетdistinct.

7. Заключение

In this article, we covered a few ways to remove repeated characters from a string in Java. Мы также рассмотрели временную и пространственную сложность каждого из этих методов.

Как всегда, фрагменты кода можно найтиover on GitHub.