Всем привет! Я решил углубленно изучить динамическое программирование и поделиться с вами опытом. Недавно я обнаружил довольно интересный план обучения на LeetCode (https://leetcode.com/studyplan/dynamic-programming/), взял его за основу - и полностью завершил, решив все задачи (50/50).

Собственно, это весьма мощный челлендж - 36 задач Medium-уровня и 10 задач Hard-уровня, что весьма полезно для развития и соответствует реальной пропорции сложности задач на реальных собеседованиях
Очень радует, что задачи сгруппированы по паттернам (10 штук) и отсортированны по сложности внутри каждого паттерна, а также вручную подобранны редакторами LeetCode - это намного приятнее решения рандомных задач из тега DP
Собственно, я потратил 24 дня на решение всех задач. Для меня зона комфорта - это 2 medium-задачи в день, но под конец у меня накопилась компетенция и hard-задачи уже перестали отличаться от medium
Я занимался 2-4 часа в день по утрам в одно и то же время, чтобы выработать привычку
Перед практикой я около месяца читал теорию (50 страниц главы по DP из CLRS), и прорешал большую часть упражнений на построение и анализ ДП-алгоритмов на бумаге
У меня накопилась довольно большая математическая подготовка за 5 лет - нужно снимать сливки. В 2020-2022 я неплохо подтянул дискретную математику и Calculus, а в 2023-2025 вложился в фундамент математики и решил более 60% проблем\пробелов в понимании, которые у меня были, включая самые глубокие проблемы в теории типов, логике и теории множеств.
Понимание моделей вычисления - очень помогает. В 2025 я написал на Java 3 модели - Машина Тюрига, лямба-исчисление и RAM-модель. Еще я порабоал с JVM-моделью вычисления поближе (Jasmin) - тоже очень откликается
Собственно, именно RAM-модель используется как теорическая база для LeetCode. Ее инструкции являются чем-то вроде математического ассемблера и я держу ее в голове и иногда программирую на ней напрямую
Глубокое погружение в контекст - это очень круто. Я сейчас не работаю и могу на 100% посвятить себя алгоритмам и думаю о них круглые сутки. Кроме решения задач в LeetCode, у меня много всяких сторонних активностей, релеватных к алгоритмам - задаю много вопросов ChatGPT или Google по мере их возникновения, читаю статьи, сижу на r/LeetCode, и так далее
LeetCode Premium того стоит - покупайте его, не задумываясь
Если бы я сейчас работал, то (скорее всего) не получилось бы так глубоко погрузиться в ДП и войти во флоу с решением задач высокой сложности
Если я пойду собеседоваться, то я оцениваю свою вероятность успеха в задачах ДП как 0.8, а если интервьювер будет помогать и подсказывать - то 0.95. И это в случае классического собеседования (LeetCode или блокнот). А если будет гибридный собес с AI, то вероятность успеха будет еще выше
Я довольно активно использую разговорные возможности ChatGPT Plus (advanced voice mode) и созваниваюсь 1 час в день, чтобы поболтать с моделью 4o и обсудить разные темы и вопросы. Это дает полное погружение в обучении и замыкает круг
Я не дебажу. Совсем. Только анализ алгоритмов в уме, и отправка задачи на проверку при уверенности в корректности. Благодаря такому подходу, экономится много времени и сил. А еще у меня было 5-medium задач и 1 HARD-задача, которые были ACCEPTED с первой попытки (!!!). Если алгоритм корректен, не важно, какие там тест-кейсы и сколько их - задача пройдет
Я редко заглядываю в Solutions - только в 20% от задач. В идеале, можно полностью работать на математической интуиции и импровизировать/синтезировать свой алгоритм. Это намного интереснее и приятнее, чем каждый паттерн задачи разбирать по Solutions и "натаскиваться" на типовые задачи
Еще я заметил, что формальная логика (классическая) - очень помогает с HARD-задачами, декомпозировать их и сделать простыми, закон исключённого третьего прямо на регулярной основе применяю
DP остается релевантным и полезным, так как эффективно решает задачи оптимизации, которые часто встречаются в бизнесе
Итог - глубокое погружение в алгоритмическую парадигму помогает отличить ее от других парадигм и четко видеть плюсы\минусы\границы применения, ревьювить и направлять AI при написании сложных алгоритмов.

Если вам понравилась статья вы хотите меня поддержать - напишите как можно больше полезной обратной связи (в комментариях или на почту kciray8@gmail.com).
Будет классно, если вы поделитесь своим опытом, секретами повышения Leetcode-производительности, а также особыми методиками обучения (если они у вас есть).
Комментарии (12)

IceGlance
11.02.2026 13:17"Если алгоритм корректен, не важно, какие там тест-кейсы и сколько их - задача пройдет"
Сортировка пузырьком вполне корректный алгоритм, но пройдет ли он все тест кейсы?

kciray Автор
11.02.2026 13:17Я имел в виду немного другое в том контексте, в котором это написал. Имел в виду, если вы пишете корректный + оптимальный алгоритм, в котором вы уверены на 100% - он сработает

LORDDREGS
11.02.2026 13:17Здравствуйте, прочитал вашу статью она очень интересная и полезная. Я бы хотел у вас спросить совета: сам лично изучаю алгоритмы и язык программирования (С++ и питон). По С++ смотрю гайды и объяснения по поводу различного уровня задач на литкоде (изи/медиум), читаю метанит и learncpp. Но пока у меня проблемы до DP, я не дошёл и пока не умею пользоваться, подскажите пожалуйста как научиться хорошо решать на собеседованиях задачи чтобы их успешно проходить? Готовлюсь к весне чтобы попробовать попасть на Летнюю стажировку в Яндексе/Сбере, уделяю 1 час изучению и написанию кода(если бы не советовал учёба в вузе то уделял бы больше), и пишу мини пет проекты(клиентский HTTP/TCP сервер на С++ и на питоне свой RNA folding). Может быть вы знаете что мне не хватает или в какую тему глубже капнуть?

kciray Автор
11.02.2026 13:17Попробуйте начать с теории и пару глав из CLRS пройти + упражнения на бумаге поделать, а уже потом переходить к LC

LORDDREGS
11.02.2026 13:17Спасибо за ответ, просто я планирую подготовиться и попасть на оплачиваемую стажировку в какой-нибудь бигтех с последующим трудоустройством (весной и летом у Яндекса, Сбера и Тинькоффа много открывается направлений), но пока подготовка страдает мало знаю легаси, STL и как вы писали в своей статьей DP. Могу пока работать с map, sort, arrays, set, vector, графы и деревья изучаю но пока есть пробелы

Forigen
11.02.2026 13:17В каком направлении разработки действительно стоит уделять столько времени алгоритмике? Имхо это не совсем целесообразно когда речь идет о прикладной веб разработке, но в то же время я признаю что алгоритмические задачи отлично структурируют мышление в решении любых проблем программирования

kciray Автор
11.02.2026 13:17в то же время я признаю что алгоритмические задачи отлично структурируют мышление в решении любых проблем программирования
Вот именно) Так что, в любом направлении стоит уделять много внимания алгоритмам

wataru
11.02.2026 13:17В бигтехе это постоянно вылезает. Особенно на бакенде и в клиентских (десктопных и мобильных) приложениях. На фронте в веб-разработке этого сильно меньше, но иногда тоже вылезает, если у вас что-то посложнее тривиальной формочки, а в бигтехе это часто. У меня пара статей с примерами есть тут на хабре: Алгоритмы нужны программистам.
d_ilyich
У меня "проблема" с табличным DP. Даже перевести рекурсивное решение в табличное -- уже ступор. Смотрел видео, решал на бумажке: когда объяснённую задачу прорешиваешь -- вроде, понятно; но с нуля -- никак. Возможно, сказывается нехватка фундаментальных знаний и опыта.
kciray Автор
Попробуй представить (или нарисовать) дерево решений и начать его проработку от листьев к корню. Мне тоже первое время рекурсивное решение с мемоизацией было приятнее, но потом я полюбил табличное даже больше - оно более компактное, не нужно писать лишних функций и структур данных.
P.S.: Но некоторые задачи не нужно переводить от рекурсивного в табличное - их лучше решать в рекурсивном, и наоборот. Итог - выбирай тот подход, который по задаче приятней
wataru
Надо формализовать решение. Когда вы выпишите математические функции, это все можно перевести в код не приходя в сознание. Потренеруйтесь это делать на куче задачек и потом станет легко.
В DP вам всегда надо обозначить функцию. Словами, формально определить ее. Вроде F(параметры) - это какое-то что-то при условии параметров.
Например: F(x,y) - максимальная сумма ячеек в пути в матрице с ходами влево-вниз, заканчивающихся в клетке x,y. F(n) - n-ое число фибоначчи. F(v, f) - минимальное количество вышек, расставленных в поддереве вершины v, так что все вершины в поддереве покрыты вышкой, кроме корня, а корень поддерева обязательно покрыт, если f=true. F(n,k) - количество способов разбить n на убывающие слагаемые такие, что первое не больше k.
Эти функции считают что-то: максимум, количество или какой-то оптимум среди каких-то объектов на множестве заданном параметрами.
Потом вам надо выписать рекуррентное соотношение: как функция F считается. В этом соотношении она будет считаться через саму себя. Для этого помогает как-то сгрупировать все объекты, с которыми функция работает. Вот эти параметры они задают какое-то множество чего-то. Путей в матрице, способов покрасить дерево, разбиений числа на слагаемые. Надо их как-то сгрупировать, чтобы получившееся подмножество описывалось такими же параметрами. В пути можно зафиксировать предпоследнюю вершину, в раскраске поддерева зафиксировать цвет корня и т.д. В каждом отдельном подмножестве вы ищите ответ той же функцией и объединяете ответы через сумму, максимум или что-то такое, что у вас в определении функции идет.
Уже посмотрев на эту формулу вы можете понять, в какую сторону идет зависимость, как параметры изменяются.
Потом вам надо обозначить базу. F от каких-то фиксированных параметров должна быть зафиксирована. Например, лучший путь из левого верхнего угла (0,0) в (0,0) единственен и вы все про него знаете. F(0,0) тут не надо считать. В поддереве из одного листа тоже все считается руками. В разбиении числа 1 на слагаемые есть только один вариант. И т.д.
Потом вам надо обозначить, где ответ - F от каких параметров решит вашу исходную задачу.
Потом уже можно реализовать рекурсивную функцию, просто переведя математическую формулу на язык програмимрования. А можно сделать таблично. Заведите таблицу F с теми же индексами, какие у вас параметры в функции. Посмотрев на формулу, разберитесь в каком порядке надо пустить циклы, чтобы все нужные для вычисления значения были подсчитаны перед использованием. Ну тупо, вот у вас F(x,...) зависит от F(x-1,...), значит x должен увеличиваться. С порядком циклов чуть-чуть сложне, тут может помочь нарисовать таблицу на бумаге, и из клеточки провести стрелочки в те, от которых клетка зависит, и подумать, в каком порядке обойти таблицу, чтобы вы никогда не шли по стрелочке, а только против них.
Ну и в цикле раелизуйте математическую формулу, только вместо вызовов рекурсивных функций берите значения из массива. Или можно вообще просто в цикле вызвать вашу изначально рекурсивную функцию, только вместо рекурсивных вызовов обращайтесь внутри к таблице.
Потом можно научиться писать более простой код за счет размазывания вычислений. Иногда проще не считать конкретную ячейку через предыдущие, а наоборот, смотреть, для каких ячеек текущая будет использоваться. И, если у вас там сумма в формуле, просто прибавлять текущее значения в следующие ячейки.
Потом можно научиться замечать, что в таблице всегда используются, допустим, 2 последние строки. И тогда не надо ее всю хранить. Или, как в числах фибоначчи, только 2 последних числа, вот их и храним.