Предположим, что у меня есть два списка с именами a и b обоих размеров n, и я хочу выполнить следующую операцию установки среза с k

a[:k] = b[:k]

На Сложности времени вики-страницы Python говорится, что сложность настройки среза равна O (n + k). ) где k - длина среза. Я просто не могу понять, почему это не просто O (k) в вышеуказанной ситуации.

Я знаю, что срезы возвращают новый список, так что это O (k), и я знаю, что список хранит свои данные непрерывно, поэтому вставка элемента в середину заняла бы O (n) времени. Но вышеуказанная операция может быть легко выполнена за O (k) время. Я что-то пропустил?

Кроме того, есть ли документация, где я могу найти подробную информацию о таких проблемах? Должен ли я посмотреть на реализацию CPython?

Спасибо.

8
Caveman 18 Дек 2015 в 16:25

3 ответа

Лучший ответ

O (n + k) - это средний регистр , который включает необходимость увеличивать или уменьшать список, чтобы отрегулировать количество вставленных элементов для замены исходного среза.

В вашем случае, когда вы заменяете срез равным количеством новых элементов, реализация занимает всего O (k) шагов. Но с учетом всех возможных комбинаций количества вставленных и удаленных элементов, случай средний должен переместить n оставшихся элементов в списке вверх или вниз.

См. list_ass_slice функцию для точного реализация.

7
Martijn Pieters 18 Дек 2015 в 13:48

Вы правы, если хотите узнать точные детали, лучше использовать источник. Реализация настройки среза для CPython: в listobject.c .

Если я правильно прочитал, это будет ...

  1. Подсчитайте, сколько новых элементов вы вставляете (или удаляете!)
  2. Сдвиньте n существующих элементов списка на достаточное количество мест, чтобы освободить место для новых элементов, в худшем случае - время O (n) (когда каждый элемент списка должен быть смещен).
  3. Скопируйте новые элементы в только что созданное пространство, потратив O (k) времени.

Это составляет в целом O (n + k).

Конечно, ваш случай, вероятно, не самый худший: вы изменяете последние k элементов списка, поэтому может не потребоваться смещение вообще, что снижает сложность до ожидаемой O (k). Однако это не так в целом.

2
Wander Nauta 18 Дек 2015 в 13:49

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

-1
piman314 18 Дек 2015 в 13:32