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

Перевод статьи автора Ashish Pratap Singh. Авторы перевода: Java-разработчики Никита С. и Антон П.
Перевод статьи автора Ashish Pratap Singh. Авторы перевода: Java-разработчики Никита С. и Антон П.

На сегодняшний день алгоритмические задачи встречаются не только в FAANG. Многие компании и на отечественном рынке всё чаще вводят дополнительный алгоритмический этап на собеседовании – и знание алгоритмов становится отличным «плюсиком» не только при трудоустройстве, но и в решении повседневных задач. Взглянем подробнее на эти паттерны.


Прорешав более 1500 задач в LeetCode, я пришёл в такому выводу:

LeetCode - это не столько о том, сколько задач ты решил, сколько о том, сколько паттернов ты знаешь.

Знание паттернов поможет вам решать больше задач за меньшее время и быстрее определить подход к решению задачи, с которой вы раньше не сталкивались.

В ��той статье мы разберём 15 видов паттернов, которые сделали мой опыт в LeetCode менее болезненным. Я подробно разберу каждый из них и оставлю ссылки на задачи в LeetCode, чтобы вы могли попрактиковаться.

1. Префиксные суммы (Prefix Sum)

Паттерн 1: Префиксные суммы
Паттерн 1: Префиксные суммы

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

Когда использовать: в ситуации, когда нужно выполнить несколько запросов сумм к подмассиву или вычислить совокупные суммы.

Пример задачи:

Дан массив nums. Вычислите сумму элементов в диапазоне [i, j].

Пример:

  • Вход: nums = [1, 2, 3, 4, 5, 6], i = 1, j = 3

  • Выход: 9

Объяснение:

  • Создаём префиксный массив: P = [1, 3, 6, 10, 15, 21]

  • Сумма элементов будет равна [i, j] = P[j] - P[i-1] (при i > 0)

Применимо к задачам:

Пример решения на Java: ссылка

2. Два указателя (Two pointers)

Паттерн 2: Два указателя
Паттерн 2: Два указателя

Паттерн двух указателей использует два указателя для обхода массива или списка. Часто применяется для поиска пар элементов, удовлетворяющих определённому условию.

Когда использовать: при работе с отсортированными массивами или списками, где нужно найти пары, удовлетворяющие условию (например, сумма = target).

Пример задачи:

Найти два числа в отсортированном массиве, сумма которых равна заданному значению.

Пример:

  • Вход: nums = [1, 2, 3, 4, 6], target = 6

  • Выход: [1, 3] (индексы)

Объяснение:

  • Инициализируем указатели: left = 0, right = len(nums) – 1

  • Проверяем сумму элементов по двум указателям

  • Если nums[left] + nums[right] == target → нашли решение

  • Если сумма меньше — двигаем left вправо

  • Если сумма больше — двигаем right влево

Применимо к задачам:

Пример решения на Java: ссылка

3. Скользящее окно (Sliding Window)

Паттерн 3: Скользящее окно
Паттерн 3: Скользящее окно

Шаблон скользящего окна используется для поиска подмассива или подстроки, удовлетворяющей определённому условию. Он оптимизирует временную сложность за счёт поддержания «окна» фиксированного или переменного размера.

Когда использовать: при работе с непрерывными подмассивами или подстроками.

Пример задачи:

Найти максимальную сумму подмассива размера k.

Пример:

  • Вход: nums = [2, 1, 5, 1, 3, 2], k = 3

  • Выход: 9

Объяснение:

  • Считаем сумму первых k элементов

  • Затем «скользим» окно: вычитаем уходящий элемент, прибавляем входящий

  • Отслеживаем максимальную сумму

Применимо к задачам:

Пример решения на Java: ссылка

4. Быстрый и медленный указатели (Fast & Slow Pointers)

Паттерн 4: Быстрый и медленный указатели
Паттерн 4: Быстрый и медленный указатели

Этот шаблон (известен как «черепаха и заяц») используется для обнаружения циклов в связных списках и других структурах.

Когда использовать: когда нужно определить наличие цикла, найти середину списка или решить задачи на цикличность.

Пример задачи:

Определить, содержит ли связный список цикличность.

Объяснение:

  • Инициализируем два указателя: slow (1 шаг за итерацию), fast (2 шага)

  • Если fast и slow встречаются — цикличность есть

  • Если fast дошёл до конца — цикличности нет

Применимо к задачам:

Пример решения на Java: ссылка

5. Разворот связного списка на месте (In-place Reversal of LinkedList)

Паттерн 5: Разворот связного списка на месте
Паттерн 5: Разворот связного списка на месте

Этот шаблон позволяет разворачивать часть связного списка без дополнительного пространства.

Когда использовать: когда нужно развернуть подсписок или весь список «на месте».

Пример задачи:

Развернуть подсписок с позиции m по n.

Пример:

  • Вход: head = [1, 2, 3, 4, 5], m = 2, n = 4

  • Выход: [1, 4, 3, 2, 5]

Объяснение:

  • На��одим узлы до m и после n

  • Разворачиваем участок между ними, корректируя указатели

Применимо к задачам:

Пример решения на Java: ссылка

6. Монотонный стек (Monotonic Stack)

Паттерн 6: Монотонный стек
Паттерн 6: Монотонный стек

Монотонный стек поддерживает элементы в стеке в строго возрастающем или убывающем порядке. Часто используется для поиска следующего большего/меньшего элемента.

Когда использовать: когда нужно найти ближайший больший/меньший элемент слева или справа.

Пример задачи:

Для каждого элемента массива найти следующий больший элемент. Если такого нет — вывести -1.

Пример:

  • Вход: nums = [2, 1, 2, 4, 3]

  • Выход: [4, 2, 4, -1, -1]

Объяснение:

  • Используем стек чтобы отслеживать элементы, для которых мы еще не нашли следующий больший элемент

  • Перебираем массив и извлекаем элементы из стека для каждого элемента, пока не найдем больший элемент

  • Если стек не пуст, устанавливаем результат для индекса наверху стека в текущий элемент

  • Помещаем текущий элемент в стек

Применимо к задачам:

Пример решения на Java: ссылка

7. Топ K элементов (Top ‘K’ Elements)

Паттерн 7: Топ К элементов
Паттерн 7: Топ К элементов

Этот шаблон находит K наибольших или наименьших элементов с помощью куч (heap) или сортировки.

Когда использовать: при поиске медианы, топ-K элементов в потоке.

Пример задачи:

Найти K-й по величине элемент в неотсортированном массиве.

Пример:

  • Вход: nums = [3, 2, 1, 5, 6, 4], k = 2

  • Выход: 5

Объяснение:

  • Используем минимальную кучу (min-heap) размера k, чтобы отслеживать k крупнейших элементов

  • Перебираем массив, добавляя элементы в кучу

  • Если размер кучи превышает k, удаляем из кучи наименьший элемент

  • Корнем кучи будет k-й по величине элемент

Применимо к задачам:

Пример решения на Java: ссылка

8. Перекрывающиеся интервалы (Overlapping Intervals)

Паттерн 8: Перекрывающиеся интервалы
Паттерн 8: Перекрывающиеся интервалы

Шаблон для слияния или обработки интервалов, которые пересекаются.

Когда использовать: при работе с графиками, расписаниями, объединением диапазонов.

Пример задачи:

Слить все перекрывающиеся интервалы.

Пример:

  • Вход: [[1,3], [2,6], [8,10], [15,18]]

  • Выход: [[1,6], [8,10], [15,18]]

Объяснение:

  • Сортируем интервалы по началу

  • Создаем пустой список с именем merged для хранения объединенных интервалов

  • Перебираем интервалы и проверяем, не перекрывается ли они с последним интервалом в объединенном списке

  • Если они перекрываются, объединяем интервалы, обновив время окончания последнего объединенного интервала

  • Если они не пересекаются, просто добавляем текущий интервал в объединенный список

Применимо к задачам:

Пример решения на Java: ссылка

9. Модифицированный бинарный поиск (Modified Binary Search)

Паттерн 9: Модифицированный бинарный поиск
Паттерн 9: Модифицированный бинарный поиск

Адаптация бинарного поиска для вращённых отсортированных массивов, нахождения границ и т.д.

Когда использовать: при работе с отсортированными или повёрнутыми массивами и поиске элементов.

Пример задачи:

Найти элемент в повёрнутом отсортированном массиве.

Пример:

  • Вход: nums = [4,5,6,7,0,1,2], target = 0

  • Выход: 4 (индекс)

Объяснение:

  • Выполняем двоичный поиск с дополнительной проверкой, чтобы определить, какая половина массива отсортирована

  • Затем проверяем, находится ли цель в пределах отсортированной половины

  • Если да, ищем эту половину; в противном случае ищем вторую половину

Применимо к задачам:

Пример решения на Java: ссылка

10. Обход бинарного дерева (Binary Tree Traversal)

Паттерн 10: Обход бинарного дерева
Паттерн 10: Обход бинарного дерева

Обход всех узлов дерева в определённом порядке:

  • PreOrder: корень → лево → право

  • InOrder: лево → корень → право

  • PostOrder: лево → право → корень

Когда использовать: почти во всех задачах на деревья.

Пример задачи:

Выполнить inorder-обход.

Пример:

  • Вход: root = [1, null, 2, 3]

  • Выход: [1, 3, 2]

Объяснение:

  • При неупорядоченном обходе узлы посещаются в следующем порядке: левый, корневой, правый.

  • Используем рекурсию или стек для обхода дерева в этом порядке.

Применимо к задачам:

Пример решения на Java: ссылка

11. Поиск в глубину (DFS)

Паттерн 11: Поиск в глубину
Паттерн 11: Поиск в глубину

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

Когда использовать: для обхода всех путей, генерации комбинаций, рекурсивных задач на деревья/графы.

Пример задачи:

Найти все пути от корня до листьев.

Пример:

  • Вход: root = [1,2,3,null,5]

  • Выход: ["1->2->5", "1->3"]

Объяснение:

  • Используем рекурсию или стек для прохождения каждого пути от корня к листьям.

  • Записываем каждый путь по мере прохождения.

Применимо к задачам:

Пример решения на Java: ссылка

12. Поиск в ширину (BFS)

Паттерн 12: Поиск в ширину
Паттерн 12: Поиск в ширину

Узлы исследуются уровень за уровнем в дереве или графе.

Когда использовать: для поиска кратчайшего пути в невзвешенном графе, обхода по уровням.

Пример задачи:

Выполнить уровневый обход бинарного дерева.

Пример:

  • Вход: root = [3,9,20,null,null,15,7]

  • Выход: [[3], [9,20], [15,7]]

Объяснение:

  • Используем очередь для отслеживания узлов на каждом уровне.

  • Проходим каждый уровень и добавляем в очередь дочерние элементы текущих узлов.

Применимо к задачам:

Пример решения на Java: ссылка

13. Обход матрицы (Matrix Traversal)

Паттерн 13: Обход матрицы
Паттерн 13: Обход матрицы

Обход элементов матрицы с помощью DFS, BFS и других техник.

Когда использовать: при работе с двумерной сеткой (grid) или матрицой, островами, заливкой и т.п.

Пример задачи:

Выполнить заливку (flood fill) — изменить цвет всех смежных клеток, начиная с заданной.

Пример:

  • Вход: image = [[1,1,1],[1,1,0],[1,0,1]], sr = 1, sc = 1, newColor = 2

  • Выход: [[2,2,2],[2,2,0],[2,0,1]]

Объяснение:

  • Используем DFS или BFS для перемещения по матрице, начиная с заданной ячейки.

  • Изменяем цвет соединенных ячеек на новый цвет.

Применимо к задачам:

Пример решения на Java: ссылка

14. Возврат (Backtracking)

Паттерн 14: Возврат
Паттерн 14: Возврат

Backtracking перебирает все возможные решения, откатываясь при неудаче.

Когда использовать: для задач на перестановки, комбинации, размещения, судоку и т.д.

Пример задачи:

Сгенерировать все перестановки списка.

Пример:

  • Вход: nums = [1,2,3]

  • Выход: [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]

Объяснение:

  • Используем рекурсию для создания перестановок.

  • Для каждого элемента включаем его в текущую перестановку и рекурсивно сгенерируем оставшиеся перестановки.

  • Возвращаемся назад, когда сгенерированы все перестановки для данного пути.

Применимо к задачам:

Пример решения на Java: ссылка

15. Динамическое программирование (Dynamic Programming)

Паттерн 15: Динамическое программирование
Паттерн 15: Динамическое программирование

ДП разбивает задачу на подзадачи и решает их, избегая повторных вычислений.

Когда использовать: когда есть перекрывающиеся подзадачи и оптимальная подструктура.

Подтипы ДП:

  • Числа Фибоначчи

  • Рюкзак (0/1 Knapsack)

  • Наибольшая общая подпоследовательность (LCS)

  • Наибольшая возрастающая подпоследовательность (LIS)

  • Сумма подмножества

  • Умножение цепочки матриц

Пример задачи:

Найти n-е число Фибоначчи.

Пример:

  • Вход: n = 5

  • Выход: 5 (последовательность: 0, 1, 1, 2, 3, 5)

Объяснение:

  • Используем восходящий подход для вычисления n-го числа Фибоначчи.

  • Начинаем с первых двух чисел (0 и 1) и выполняем итерацию для вычисления следующих чисел, например (dp[i] = dp[i - 1] + dp[i - 2]).

Применимо к задачам:

Пример решения на Java: ссылка

Все решения в нашем GitLab: ссылка

Комментарии (25)


  1. AdrianoVisoccini
    07.11.2025 16:07

    я бы по каждому методу по подробнее почитал бы с удовольствием
    с парой-тройкой примеров в идеале...


    1. DamonV79
      07.11.2025 16:07

      Примеры не проблема, ссылки на задачи есть, а уже в самих задачах можно посмотреть лучшие варианты решения на любом языке. Порой, это буквально несколько строчек, по этому понять алгоритм не сложно. Мне это здорово помогло, когда только начинал решать задачки на Скала, я (по привычке) использовал идеоматичный функциональный подход. Увы, по скорости он сильно проигрывает (порой, но не всегда!) императивному. Возможность подсмотреть и понять, что требуется помогла выйти в лидеры.

      Ну, а подробности, да, придется искать самому. Впрочем, неплохих книжек по алгоритмам хватает.


      1. AdrianoVisoccini
        07.11.2025 16:07

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


  1. mSnus
    07.11.2025 16:07

    Вот что должно вымереть в первую очередь в эпоху AI


    1. pavlushk0
      07.11.2025 16:07

      Индусы решающие литкод?


      1. mSnus
        07.11.2025 16:07

        И все тренажёры по зубрёжке


    1. MaDeLa Автор
      07.11.2025 16:07

      Думается, что алгоритмические задачки не вымрут. Этот скилл требовали на собеседованиях 10 лет назад, и, скорее всего, будут требовать ещё долго - даже в эпоху развитого AI. А значит и тренажёры по зубрёжке будут жить. Кстати, как относитесь к тому, что на собесах дают алготимические задачки решать? Считаете полезной практикой или устаревшей традицией?


      1. Artyomcool
        07.11.2025 16:07

        Мне это всегда казалось и продолжает казаться неплохим способом проверить замотивированность кандидата заниматься относительно длительной подготовкой к интервью. Примерно как диплом о ВО доказательство 4-6 лет "усидчивости". Поэтому с готовностью решаю алгоритмические секции, но со своей стороны при собеседованиях делаю скидку, что вообще говоря, человек не обязан знать трюк с prefix sum, будь он трижды тривиальным (когда его знаешь). Не обязан уметь вращать деревья в уме. Но если вдруг умеет и в структуры данных, и в методы работы с ними, то разговор точно пойдет и проще, и интереснее. По крайней мере, это точно интереснее, чем фреймворк А, который уже завтра будет заменён фреймворком Б.


      1. mSnus
        07.11.2025 16:07

        Это как в математике - есть отличники, которые вызубрили стандартные задачи, есть люди, которые на стандартных задачах научились решать любые. В первых нет никакого особого смысла. С программированием то же самое - тот ч кто выучил и пошёл дальше, намного полезнее того, кто выучил и застрял.


  1. Panzerschrek
    07.11.2025 16:07

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


    1. MaDeLa Автор
      07.11.2025 16:07

      Да, для паттернов это частая история. Взять в том числе гоф-паттерны: когда ты впервые с ними сталкиваешься, то не осознаёшь когда их нужно применять и стремишься их использовать даже там, где не надо. Вероятнее всего по мере решения задач, придёт понимание относительно того, где какой паттерн применить. Они сами всплывут в памяти и вам останется лишь взглянуть в статью, чтобы использовать её как шпаргалку


  1. apcs660
    07.11.2025 16:07

    недавно ради разогрева прорешал яндекс контест по алгоритмам; литкод несколько расслабленее и не так жестко проверяет выходы за границы времени и памяти.

    Иногда кажется что можно решить одним методом в лоб, но размерность 10^9 сразу требует упростить задачу а не решать перебором.

    Яндекс контест показался более жестким чем литкод, особенно последняя задачка в контесте крови попила.

    Вчера прислали результат - попал в топ 300 и могу соскочить с алго-интервью в Яндекс, но оно мне не надо... вообще подумываю а зачем я поперся на эти алгоритмы? Наверное потому что на рынке тишина а тренироваться нужно. На собеседовании по алгоритмам все было просто, основная проблема была не задача а непривычность решать задачу в свете софитов, я просто не мог думать. Решил на автомате, спинным мозгом, долго тупил, но в итоге прошел интервью.

    Систем дизайн интервью это было что то нечто - слишком примитивное, интервьювер не в духе, я тупил "а что здесь собственно, нужно дизайнить???". Забыл какие то мелкие вещи на которые даже не смотрел. Так понимаю, ожидалось что я должен заучить типовые паттерны и отбарабанить их за полчаса (полчаса требования собирал только). Как то само по себе интервью чуть не превратилось в собачью свалку... У меня за плечами крупные реальные проекты где я находил ошибки (достаточно важные) уже после подписания дизайна. В реальности так никто не работает, времени обычно достаточно все спокойно обдумать. Рисовать схему за час полтора это базовая подготовка пехоты.

    Пройду еще final интервью и наверное закруглюсь, что то работать в Яндексе расхотелось, впечатление что колесо сансары по фильтрации кандидатов крутится само по себе, как побочный бизнес и в итоге вряд ли будет толк. С точки зрения подготовки к интервью, повышения психологической устройчивости и тд, Яндекс дает хорошую возможность для кандидатов, большое спасибо за это.


    1. 15432
      07.11.2025 16:07

      О, я так после final и закруглился, даже офер не послушал (а зря, ради интереса можно было бы)


    1. MaDeLa Автор
      07.11.2025 16:07

      Спасибо, что поделились - крутой, жизненный рассказ. Прямо видно, как по ходу колесо сансары проверок превращается в проверку не алгоритмов, а нервной системы ))

      System Design - отдельная боль. Прекрасно вас понимаем.

      Кстати, если Яндекс не выберет - не расстраивайтесь. Выбирайте MaDeLa :) У нас тоже бывают интересные задачки, но больше с доверием к опыту. Мы ценим тех, кто умеет кодить, применяя здравый смысл.

      Удачи на финале - даже если просто для галочки


      1. apcs660
        07.11.2025 16:07

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

        Посмотрел ваш сайт - молодцы, правильным путем идете, желаю вам дальнейшего роста. У меня опыт работы в 3х стартапах - примерно представляю процесс что нужно пройти чтобы вытянуть бизнес: первый стартап в котором работал не прожил и двух лет (2000-2001 RIP); второй в котором был 2 года на ставке и 3 года на проектных контрактах, до сих пор живет, почти 30 лет уже (с 1997), но замер в размерах после того как был поглощен и стал по сути отделом; последний 3й стартап (2007-) в котором проработал 15 лет, вырос с 10 человек (когда пришел) до примерно 200 и сейчас снова сжался (подрубило СВО, аутсорсинг был в России, на индусов переключиться не получилось - да они и сами с зубами). Был у меня опыт аутстаффа, в IBM - бегал с их бейджиком на проектах. Самый веселый опыт, если честно - много полетов, хорошие проекты. С женой потом объездили пару стран на мили и бонусы в отелях. Если бы не семейные дела и моя прикованность к России сейчас, я бы снова рванул в IBM консалтинг или подобное.

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

        При управлении нужны обратные связи, положительные и отрицательные, понятная схема мотивации (конфета должна даваться сразу), вовлечение (ощущение себя частью компании), отрицательная обратная связь тоже важна (наказание). Если обратная связь разбалансирована и происходит "заболачивание" - компания впадает в фазу застоя, старения и гибнет. Будете расти - не расслабляйтесь.

        У нас болевая точка началась когда компания вышла на уровень ~10 миллионов долларов официальной прибыли и пара владельцев ушли "лежать на пляжах", наняв себе CEO и прокладку из помощников - старичков при этом оставили на своих местах. Но все быстро меняется и нужно держать нос по ветру - пока СЕО писали отчеты в стиле "все хорошо прекрасная маркиза", копился технический долг, отставание и что самое главное, уходили (от скуки!) хорошие специалисты. Платили выше рынка, но люди уходили.

        Примерно за 5 лет все протухло, разложилось, СЕО в итоге сбежали и когда владельцы попытались все снова собрать - не получилось. А тут еще проблемы с СВО - если вопрос как платить, решить смогли то требования клиентов о закрытии доступа и тд разорвал цепочки.


  1. Pochemuk
    07.11.2025 16:07

    Что-то не понял я "Шаблон № 9". Может быть потому что машинный перевод корявый?

    Лучше вот такие задачки решить:

    1. Нахождение медианного элемента: Найти медианный элемент в неотсортированном массиве за время O(n).

    2. Поменять местами две части массива (не обязательно равной длины) за время O(n) и с использованием O(1) дополнительной памяти (на месте).

    3. Нахождение максимальной нулевой подматрицы: Дана прямоугольная матрица n:m, заполненная, преимущественно, нулями. Некоторым её элементам присвоены единичные значения. За время O(n*m) найти наибольший (по количеству элементов - площади) прямоугольник, состоящий из одних нулей.


  1. DanteLFC
    07.11.2025 16:07

    Привет, спасибо за статью, как раз приходится снова вспоминать все эти истории и готовиться. В пункте 7 в примере по ссылке https://github.com/madela-team/Java/blob/master/leet-code-algorithms/src/main/java/org/madela/TopKElements.java как будто если поменять входной массив на {3, 2, 1, 6, 5, 4}; то выводом будет 6 как 2й самый большой элемент, а ведь он 1й по размеру. Или я что-то не так понял (сам шарпист, а не джавист, могу не знать нюансов класса)


    1. DaNuN0103
      07.11.2025 16:07

      Там используется приоритетная очередь PriorityQueue. В конструкторе по умолчанию используется natural ordering или сортировка по возрастанию, если по-нашему. Следовательно в каком бы порядке в эту очередь не делать ставки head будет равен минимальному элементу. А так как размер кучи k, то наибольший k элемент массива.
      P.s если, например, создать очередь и добавить элементы 2, 3, 1
      PriorityQueue<Integer> prior = new PriorityQueue<>();
      prior.add(2);
      prior.add(3);
      prior.add(1);

      то System.out.println(prior) - выведет [1, 3, 2]
      а последовательный вызов poll() - 1, 2, 3
      while(!prior.isEmpty()){
      System.
      out.print(prior.poll());
      }


      1. DanteLFC
        07.11.2025 16:07

        Спасибо! Упустил этот момент: когда быстро гуглил про этот класс при разборе примера


  1. nomorewar
    07.11.2025 16:07

    А в чем смысл первого шаблона (префиксный массив)? Сам префиксный массив делать же затратно, нет? Например, если там миллион элементов. Или миллиард.


    1. artemi1x
      07.11.2025 16:07

      Тоже не понял для чего, пример не совсем удачный, ведь можно просто просуммировать...


    1. wataru
      07.11.2025 16:07

      Там же написанно - когда надо много раз искать сумму. Вы тратите O(n) времени на предподсчет и потом за O(1) считаете сумму. Навиное же решение считает одну сумму за O(n). Если надо m раз считать сумму, то наивное решение будет за O(nm), а с префиксными суммами - O(n + m). Что лучше почти всегда.

      Плюс, переход к префиксным суммам упрощает задачи где вы ищете массивы с каким-то свойством суммы, ибо там сумма кучи переменных заменяется на разность всего двух. Вот там примеры даже есть в статье, вроде: найти количество подмассивов дающих заданную сумму. В терминах префиксных сумм - надо найти пары чисел с заданной разницей. Эта задача гораздо проще.


  1. King_Louis
    07.11.2025 16:07

    Прочитайте и потренируйтесь на книге Грокаем Алгоритмы, это будет полезнее


    1. MaDeLa Автор
      07.11.2025 16:07

      Подтверждаем: отличная книга, хороший совет. Но одно другому не мешает. Мы в MaDeLa считаем, что чем шире арсенал подходов к решению задач, тем лучше. И классические книги, и практические паттерны вроде тех, что в статье, отлично дополняют друг друга.


      1. King_Louis
        07.11.2025 16:07

        Согласен