Какова асимптотическая сложность операции удаления элемента из начала слайса в Go?

Ответ

Операция удаления элемента из начала слайса в Go имеет линейную сложность O(n), где n — количество оставшихся элементов.

Почему O(n)?

Слайс в Go — это обертка над непрерывным участком памяти (массивом). Чтобы удалить первый элемент, необходимо сдвинуть все последующие элементы на одну позицию влево, чтобы заполнить образовавшееся пустое место. Эта операция копирования занимает время, пропорциональное количеству сдвигаемых элементов.

Как это выглядит в коде?

Канонический способ удаления первого элемента — использование append:

// Исходный слайс
slice := []int{10, 20, 30, 40, 50}

// Удаляем первый элемент (10)
// Эта операция копирует элементы {20, 30, 40, 50} в начало того же базового массива.
slice = append(slice[:0], slice[1:]...)

// Результат: [20 30 40 50]

Важное замечание: Хотя операция s = s[1:] сама по себе имеет сложность O(1) (она просто меняет указатель и длину слайса), она не удаляет элемент в полном смысле, а лишь создает новый слайс, который не включает первый элемент. Память под "удаленным" элементом не освобождается, пока на него есть ссылки.

Альтернативы

Если в вашей задаче требуется частое удаление элементов из начала коллекции, рассмотрите использование других структур данных:

  • Двусвязный список (container/list): Удаление из начала или конца списка имеет сложность O(1).
  • Кольцевой буфер (реализуется вручную): Также обеспечивает операции добавления/удаления с обоих концов за O(1).