Какая временная сложность копирования массива в Swift?

Ответ

O(n) в худшем случае, где n — количество элементов. Однако благодаря оптимизации Copy-on-Write (CoW) фактическое копирование происходит отложенно.

Как это работает:

  1. При присваивании (let b = a) создается новая ссылка на те же данные — O(1).
  2. Физическое копирование буфера памяти происходит только при попытке изменить один из массивов (мутация). Это и есть O(n), так как все элементы должны быть скопированы.

Пример:

var arrayA = [1, 2, 3] // Выделен буфер
var arrayB = arrayA    // O(1). Оба массива ссылаются на один буфер.

arrayB.append(4)       // O(n). Срабатывает CoW: для arrayB создается отдельная копия буфера, затем добавляется элемент.

Почему это важно: CoW оптимизирует производительность, избегая ненужных копий для массивов, которые только читаются.

Ответ 18+ 🔞

Э, слушай, ты вот про массивы в Свифте говоришь, про копирование. Ну, вроде как, блядь, присвоил один массив другому — и всё, пиздец, копия готова, O(n) и прочая хуйня. Ан нет, сука!

Тут, понимаешь, хитрая жопа под названием Copy-on-Write (CoW). Это как твой друг, который говорит: «Да, конечно, я помогу переехать», а сам, блядь, ждёт, пока ты уже начнёшь диван с пятого этажа тащить, и только тогда охуевает и вспоминает про «спину».

Как эта мартышлюшка работает:

  1. Ты делаешь let b = a. Ну, типа, скопировал. А на самом деле нихуя не скопировал! Создалась новая бумажка, где написано «склад такой-то, ящик №1». И всё, O(1), ебать мои старые костыли. Оба массива тычут пальцем в одну и ту же кучу данных.
  2. Всё идёт по плану, пока одному из этих ушлёпков не взбредёт в голову что-то изменить. Вот тут-то, сука, и начинается цирк. Система охуевает: «Так, стоп, а если я поменяю тут, то и другому чуваку достанется, а он, пидарас шерстяной, не просил!». И только тогда, с глубоким вздохом, она идёт и делает настоящую, полную, жирную копию всех данных — вот это уже O(n), потому что каждый элемент надо перетащить.

Смотри, как это в коде выглядит, блядь:

var arrayA = [1, 2, 3] // Выделили склад, завезли три ящика.
var arrayB = arrayA    // O(1). Просто дали arrayB тот же адрес склада. Ничего не копировали, нихуя!

arrayB.append(4)       // А ВОТ ТУТ ПИЗДЕЦ! (O(n))
                       // CoW просыпается: «Опа, мутация!».
                       // Для arrayB арендует новый склад, копирует туда все три старых ящика, и только потом ставит свой, четвёртый.

И зачем этот геморрой, спросишь? А затем, чувак, что в 99% случаев ты эти массивы просто читаешь, передаёшь, смотришь на них. И зачем, блядь, каждый раз городить копии, тратить память и время? Вот эта оптимизация и спасает жопу. Пока не лезешь менять — живёшь припеваючи. Полез — получи в табло полное копирование. Ёперный театр, но умно, блядь.