Дан фрагмент кода на Python, реализующий стек: def pop(stack): return stack.pop(0) — объясните проблему производительности и предложите исправление с анализом сложности
Проблема: вызов `stack.pop(0)` на Python-списке удаляет первый элемент и сдвигает все последующие элементы влево — это требует копирования/перемещения примерно n−1n-1n−1 элементов для списка длины nnn. Поэтому одна такая операция имеет сложность O(n)\mathcal{O}(n)O(n). Исправление (если нужен стек — LIFO): использовать конец списка как вершину стека: ``` def pop(stack): return stack.pop() # удаление с конца — амортизированно O(1) # добавление: stack.append(x) ``` Сложность: каждая операция `append`/`pop()` амортизированно O(1)\mathcal{O}(1)O(1). Для mmm операций общая сложность O(m)\mathcal{O}(m)O(m). Если нужен очередь (FIFO): используйте collections.deque и `popleft()`: ``` from collections import deque q = deque() q.append(x) # добавление справа — O(1) q.popleft() # удаление слева — O(1) ``` Сложность: `popleft()` и `append()` — O(1)\mathcal{O}(1)O(1) каждая; для mmm операций общая сложность O(m)\mathcal{O}(m)O(m). Сравнение: последовательность из mmm вызовов `pop(0)` на списке может потребовать суммарно O(m2)\mathcal{O}(m^2)O(m2) времени, тогда как эквивалентное число операций с `append`/`pop()` или с `deque` — O(m)\mathcal{O}(m)O(m).
Исправление (если нужен стек — LIFO): использовать конец списка как вершину стека:
```
def pop(stack):
return stack.pop() # удаление с конца — амортизированно O(1)
# добавление: stack.append(x)
```
Сложность: каждая операция `append`/`pop()` амортизированно O(1)\mathcal{O}(1)O(1). Для mmm операций общая сложность O(m)\mathcal{O}(m)O(m).
Если нужен очередь (FIFO): используйте collections.deque и `popleft()`:
```
from collections import deque
q = deque()
q.append(x) # добавление справа — O(1)
q.popleft() # удаление слева — O(1)
```
Сложность: `popleft()` и `append()` — O(1)\mathcal{O}(1)O(1) каждая; для mmm операций общая сложность O(m)\mathcal{O}(m)O(m).
Сравнение: последовательность из mmm вызовов `pop(0)` на списке может потребовать суммарно O(m2)\mathcal{O}(m^2)O(m2) времени, тогда как эквивалентное число операций с `append`/`pop()` или с `deque` — O(m)\mathcal{O}(m)O(m).