Стек
Удалить соседние дубликаты в строке
Удалить все пары одинаковых соседних символов
Постановка задачи
Описание (LeetCode - 1047. Remove All Adjacent Duplicates In String)
Дана строка s, состоящая из строчных английских букв. Нужно удалять соседние
одинаковые символы, пока такие пары существуют.
Верните строку, которая получится после всех удалений.
Пример 1:
s = "abbaca"
Результат:
"ca"
Пояснение:
Сначала удаляем "bb" и получаем "aaca". Затем удаляем "aa" и получаем
"ca".
Пример 2:
s = "azxxzy"
Результат:
"ay"
Ограничения:
1 <= s.length <= 10⁵sсостоит из строчных английских букв.
Решение
Если удалить пару символов в середине строки, рядом могут оказаться символы, которые раньше не были соседями. Поэтому простого прохода с удалением из строки недостаточно: после каждого удаления пришлось бы возвращаться назад.
Стек позволяет легко решить эту проблему. Стек хранит текущую строку после всех удалений, которые уже можно было сделать.
Идея решения:
Идем по символам строки слева направо. Для каждого символа смотрим на вершину стека:
- Если стек не пуст и верхний символ равен текущему, значит, мы нашли соседнюю пару. Удаляем верхний символ из стека и не добавляем текущий.
- Иначе кладем текущий символ в стек.
В конце стек содержит ответ.
Рассмотрим пример s = "abbaca":
a- стек пуст, кладем.
b- на вершинеa, кладем.
b- на вершине тожеb, удаляем из стека.
a- на вершине тожеa, удаляем.
c- кладем.
a- кладем. Ответ:"ca".
Стек здесь работает как аккумулятор результата и содержит уже обработанный префикс строки. Когда приходит новый символ, мы сравниваем его только с вершиной стека.
Оценка сложности
Временная сложность
Мы обрабатываем каждый символ один раз. Каждая операция со стеком занимает
O(1), поэтому временная сложность равна O(n).
Пространственная сложность
В худшем случае удалений не будет, и стек сохранит все символы. Пространственная
сложность равна O(n).
Код решения
Приведем код решения.
func removeDuplicates(s string) string {
stack := []byte{}
for i := 0; i < len(s); i++ {
ch := s[i]
if len(stack) > 0 && stack[len(stack)-1] == ch {
stack = stack[:len(stack)-1]
} else {
stack = append(stack, ch)
}
}
return string(stack)
}Итоги
Задача Remove All Adjacent Duplicates In String - это простой пример стека, который хранит уже обработанную часть строки.
- Суть алгоритма: текущий символ сравнивается только с вершиной стека. Если они равны, пара удаляется. Если нет, символ становится новым кандидатом для будущего удаления.
- Эффективность:
- Временная сложность:
O(n), так как каждый символ добавляется и удаляется не более одного раза. - Пространственная сложность:
O(n), если в строке нет удаляемых пар.
- Временная сложность:
- Граничные случаи:
- Все символы удаляются: стек становится пустым, ответом будет пустая строка.
- Удалений нет: стек постепенно накопит всю исходную строку.
- Оптимальное решение: стек избавляет нас от повторных проходов по строке. После удаления пары предыдущий символ автоматически становится вершиной и сразу готов к сравнению со следующими символами.