Какие знаешь подходы к скорости памяти алгоритма

Ответ

Вот основные подходы к оптимизации использования памяти в алгоритмах:

  1. Жадные алгоритмы - принимают локально оптимальные решения на каждом шаге, экономя память (например, алгоритм Дейкстры).

  2. Разделяй и властвуй - рекурсивное разбиение задачи на подзадачи (быстрая сортировка, сортировка слиянием).

  3. Динамическое программирование - запоминание промежуточных результатов (кеширование). Пример с числами Фибоначчи:

function fib(n, memo = {}) {
  if (n in memo) return memo[n];
  if (n <= 2) return 1;
  memo[n] = fib(n-1, memo) + fib(n-2, memo);
  return memo[n];
}
  1. Итеративные решения вместо рекурсивных - избегают переполнения стека.

  2. Ленивые вычисления - откладывают вычисления до момента необходимости.

  3. Сжатие данных - использование более компактных структур данных (битовые маски, sparse матрицы).

  4. Пул объектов - повторное использование объектов вместо создания новых.

Ответ 18+ 🔞

А, слушай, смотри, вот как память в алгоритмах экономить, чтоб не жрала как не в себя. Тут, блядь, целая наука, но если по-простому, то вот основные приёмы, как хитрожопый программист выкручивается.

Жадные алгоритмы, ну, это как в жизни — хватай, что ближе и кажется вкуснее сейчас. На каждом шагу берут самое выгодное, что под руку подвернулось, и вперёд. Памяти почти не надо, живут одним днём, сука. Алгоритм Дейкстры, например, так и работает — ползёт по графу, хватает самую дешёвую вершину, и ему похуй на глобальную картину. Но иногда выстреливает, ёпта.

Разделяй и властвуй — это классика, блядь. Задача большая и страшная? Нахуй, разъёбываем её на мелкие кусочки, как картошку на оливье. Каждый кусочек решаем отдельно, а потом склеиваем обратно, но уже в красивом порядке. Быстрая сортировка, сортировка слиянием — они так и живут. Рекурсия, конечно, но если аккуратно, то память не сожрёт.

А вот динамическое программирование — это вообще магия, блядь. Ты как хитрая белка: нашёл орешек — спрятал, запомнил где. Второй раз на то же дерево полез — уже знаешь, куда лапы ставить. Вместо того чтобы тысячу раз одно и то же считать, ты результаты промежуточные кешируешь. Смотри, как с числами Фибоначчи элегантно получается:

function fib(n, memo = {}) {
  if (n in memo) return memo[n];
  if (n <= 2) return 1;
  memo[n] = fib(n-1, memo) + fib(n-2, memo);
  return memo[n];
}

Видишь? memo — это твоя записная книжка, куда ты пишешь, сколько будет fib(5), чтобы потом, когда опять спросят, не считать заново, а просто посмотреть, блядь. Экономия — овердохуищная.

Дальше, итеративные решения вместо рекурсивных. Рекурсия — это красиво, это элегантно, пока стек вызовов не лопнет у тебя в ебале, как воздушный шарик. Поэтому умные дяди часто переписывают рекурсию на циклы. Места меньше жрёт, и спать спокойнее.

Ленивые вычисления — это вообще философия, блядь. Зачем делать что-то сейчас, если можно отложить на потом? Может, и не понадобится вовсе. Как тот студент, который готовится к экзамену в последнюю ночь. Памяти не тратится до самого последнего момента — хитрая жопа.

Сжатие данных — тут уже начинается чёрная магия. Если данные разреженные (ну, матрица, где почти все нули), то хранить её целиком — это пиздец какой расточительство. Лучше использовать специальные структуры, вроде sparse матриц, или битовые маски, где в одном числе закодированы флаги. Места в разы меньше, но голову, блядь, сломать можно.

И наконец, пул объектов. Зачем каждый раз создавать новый объект, если старый уже не нужен? Выкинул из него старые данные, засунул новые — и вперёд, как многоразовая бутылка. Особенно актуально, когда объектов тысячи, и создавать каждый раз — это просто издевательство над сборщиком мусора.

Вот так, коротко и без лишней ебли. Главное — думать головой, а не надеяться, что память бесконечная. Потому что она, сука, очень даже конечная.