Перейти к основному содержимому

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

· 5 мин. чтения

1. Обзор

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

Для каждой техники мы также кратко расскажем о ее временной и пространственной сложности.

2. Использование различных

Давайте начнем с удаления дубликатов из нашей строки, используя отдельный метод, представленный в Java 8.

Ниже мы получаем экземпляр потока Int S из заданного строкового объекта. Затем мы используем отдельный метод для удаления дубликатов. Наконец, мы вызываем метод forEach для перебора отдельных символов и добавления их в наш StringBuilder : [](/lessons/b/-java-string-builder-string-buffer)

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

Временная сложность: O(n) — время выполнения цикла прямо пропорционально размеру входной строки.

Вспомогательное пространство: O(n) — так как Different использует LinkedHashSet для внутреннего использования, и мы также сохраняем результирующую строку в объекте StringBuilder .

Поддерживает порядок: Да, поскольку LinkedHashSet поддерживает порядок своих элементов.

И хотя хорошо, что Java 8 так хорошо справляется с этой задачей, давайте сравним ее с усилиями по развертыванию нашей собственной.

3. Использование indexOf

Наивный подход к удалению дубликатов из строки просто включает в себя цикл по вводу и использование метода indexOf для проверки того, существует ли уже текущий символ в результирующей строке :

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);
}
}

Временная сложность: O(n * n) — для каждого символа метод indexOf просматривает оставшуюся строку.

Вспомогательное пространство: O(n) — требуется линейное пространство, так как мы используем StringBuilder для хранения результата.

Поддерживает порядок: Да

Этот метод имеет ту же пространственную сложность, что и первый подход, но работает намного медленнее.

4. Использование массива символов

Мы также можем удалить дубликаты из нашей строки, преобразовав ее в массив символов , а затем перебрав каждый символ и сравнив его со всеми последующими символами .

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

Временная сложность: O(n * n) — у нас есть внутренний и внешний цикл, которые обходят входную строку.

Вспомогательное пространство: O(n) — требуется линейное пространство, поскольку переменная chars хранит новую копию введенной строки, и мы также используем StringBuilder для сохранения результата.

Поддерживает порядок: Да

Опять же, наша вторая попытка работает плохо по сравнению с предложением Core Java, но давайте посмотрим, чего мы добьемся в нашей следующей попытке.

5. Использование сортировки

В качестве альтернативы, повторяющиеся символы можно удалить, отсортировав нашу входную строку, чтобы сгруппировать дубликаты. Для этого нам нужно преобразовать строку в массив символов и отсортировать ее с помощью метода Arrays . способ сортировки . Наконец, мы пройдемся по отсортированному массиву символов .

На каждой итерации мы будем сравнивать каждый элемент массива с предыдущим элементом. Если элементы отличаются, мы добавим текущий символ в 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]);
}
}
}

Временная сложность: O (n log n) — сортировка использует быструю сортировку с двумя опорными точками , которая обеспечивает производительность O (n log n) для многих наборов данных.

Вспомогательное пространство: O(n) — поскольку метод toCharArray делает копию входной строки .

Поддерживает порядок: Нет

Давайте попробуем это снова с нашей последней попыткой.

6. Использование набора

Другой способ удалить повторяющиеся символы из строки — использовать Set . Если нас не волнует порядок символов в нашей выходной строке, мы можем использовать HashSet . В противном случае мы можем использовать LinkedHashSet для поддержания порядка вставки.

В обоих случаях мы будем перебирать входную строку и добавлять каждый символ в Set . Как только символы будут вставлены в набор, мы пройдемся по нему, чтобы добавить их в StringBuilder и вернуть результирующую строку:

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

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

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

Временная сложность: O(n) — время выполнения цикла прямо пропорционально размеру входной строки.

Вспомогательное пространство: O(n) – место, необходимое для набора , зависит от размера входной строки; также мы используем StringBuilder для хранения результата

Поддерживает порядок: LinkedHashSet — да, HashSet — нет

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

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

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

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