Автор оригинала: Khalid Andari.
1. Обзор
В этом уроке мы обсудим несколько методов в Java о том, как удалить повторяющиеся символы из строки.
Для каждой техники мы также кратко расскажем о ее сложности во времени и пространстве.
2. Использование различных
Давайте начнем с удаления дубликатов из вашей строки с помощью метода distinct , представленного в Java 8.
Ниже мы получаем экземпляр Int S stream из данного строкового объекта. Затем мы используем метод distinct для удаления дубликатов. Наконец, мы вызываем метод forEach , чтобы перебрать отдельные символы и добавить их в наш StringBuilder :
StringBuilder sb = new StringBuilder(); str.chars().distinct().forEach(c -> sb.append((char) c));
Временная сложность: O(n) – время выполнения цикла прямо пропорционально размеру входной строки
Вспомогательное пространство: |/O(n) – поскольку distinct использует 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. Использование массива символов
Мы также можем удалить дубликаты из нашей строки, преобразовав ее в массив char , а затем зациклившись на каждом символе и сравнив его со всеми последующими символами .
Как мы видим ниже, мы создаем два цикла для и проверяем, повторяется ли каждый элемент в строке. Если дубликат найден, мы не добавляем его в 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 для сохранения результата
Поддерживает порядок: Да
Опять же, наша вторая попытка работает плохо по сравнению с основным предложением Java, но давайте посмотрим, к чему мы придем с нашей следующей попыткой.
5. Использование сортировки
Кроме того, повторяющиеся символы могут быть устранены путем сортировки нашей входной строки для группирования дубликатов. Для этого мы должны преобразовать строку в char a rray и отсортировать ее с помощью Массивов . сортировка метод . Наконец, мы проведем итерацию по отсортированному массиву char .
Во время каждой итерации мы будем сравнивать каждый элемент массива с предыдущим элементом. Если элементы отличаются, мы добавим текущий символ в 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(); SetlinkedHashSet = 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 – Нет
И теперь мы соответствуем основному подходу Java! Не очень шокирует, что это очень похоже на то, что уже делает distinct .
7. Заключение
В этой статье мы рассмотрели несколько способов удаления повторяющихся символов из строки в Java. Мы также посмотрели на время и пространство
В этой статье мы рассмотрели несколько способов удаления повторяющихся символов из строки в Java. Мы также посмотрели на время и пространство