Выбор ответа Middle Разминка: короткие функции обновлено

Spread в аккумуляторе reduce

Вопрос

Функция работает правильно, но на массиве из 100 000 элементов заметно тормозит. Почему?

const doubleAll = (arr) => arr.reduce((acc, x) => [...acc, x * 2], []);

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: На каждом шаге создаётся новый массив с копией всех предыдущих: O(n²). [...acc, x 2] копирует весь накопленный массив, и на шаге k это k операций: в сумме порядка n²/2 копирований.

Варианты ответа

  1. reduce медленнее обычного цикла for в сотню раз из-за вызова колбэка
  2. Умножение в JS медленное, потому что все числа хранятся как double
  3. На каждом шаге создаётся новый массив с копией всех предыдущих: O(n²)правильный ответ
  4. Сборщик мусора не может освободить acc, и память растёт до лимита

Разбор

[...acc, x * 2] копирует весь накопленный массив, и на шаге k это k операций: в сумме порядка n²/2 копирований. Для 100 000 элементов это миллиарды операций. Правильно: arr.map((x) => x * 2) или acc.push(x * 2); return acc;, это O(n). Сам reduce медленнее цикла незначительно. Старые массивы сборщик освобождает, проблема в объёме копирования, а не в памяти.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.