Рубрики
Без рубрики

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

Откройте для себя различные методы удаления повторяющихся символов из строки в Java.

Автор оригинала: 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();
Set 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 – Нет

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

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

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

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