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

Ответ

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

Это связано с тем, что для сохранения непрерывности данных все элементы, находящиеся после удаляемого, должны быть сдвинуты на одну позицию влево.

Классический пример (с сохранением порядка):

// Удаляет элемент по индексу, сохраняя порядок остальных элементов
func remove(slice []int, index int) []int {
    return append(slice[:index], slice[index+1:]...)
}

В этом примере append создает новый слайс, копируя в него сначала часть до удаляемого элемента (slice[:index]), а затем часть после него (slice[index+1:]). Копирование второй части и определяет сложность O(n).

Исключения и оптимизации:

  1. Удаление последнего элемента: O(1) Это самая быстрая операция, так как не требует сдвига элементов.

    slice = slice[:len(slice)-1]
  2. Удаление без сохранения порядка: O(1) Если порядок элементов не важен, можно поменять удаляемый элемент с последним и затем укоротить слайс. Это эффективный трюк.

    index := 2 // Индекс удаляемого элемента
    slice[index] = slice[len(slice)-1] // Заменяем удаляемый последним
    slice = slice[:len(slice)-1]       // Укорачиваем слайс