Привет, Хабр!
Сегодня я расскажу вам про мой путь от 0 до 500+ задач на Leetcode. Сначала, пару слов о себе: достаточно слабое образование, завалил кучу собеседований на алгоритмы (например, в Авито где-то в 2020 году), никогда не умел решать задачи, и не любил. Долгое время узнав о секции алгоритмов просто отказывался от собеседований. Сейчас не боюсь и могу. Даже в Бигтех эту секцию проходил несколько раз.
Я делал всякий фронтенд, потом стал делать бекенд (на NodeJS), но алгоритмы никогда не получались.
И вот, засучив рукава, я решил разделаться с этим безобразием раз и навсегда. Мой профиль на LeetCode на сегодняшний день выглядит так:

(при этом я не гонюсь за числом в профиле, но гонюсь за навыком)
Для кого статья: разработчики, которые пишут код, хотят прокачать навык решения алгоритмических задач, но пока не получается по разным причинам.
Кому статья не подойдет: "Мне живется хорошо, задачки ваши не нужны". Не нужны так не нужны :)
Здесь я не буду перечислять, какие задачи бывают, и как решать каждый тип. Лично мне такие статьи не помогали. Я буду описывать подходы, которые помогли мне самому, и до внедрения которых ничего не получалось.
Шаг 0. Мотивация
Одной из самых больших проблем для меня было найти мотивацию. Я понимал что решение задачек – моя слабая сторона, но не понимал, как это сделает из меня более крутого разработчика. При этом я замечал, что люди с более высокими хардскилами, чем у меня, все-таки, умеют их решать.
Понимание структур данных
Есть целый пласт задач на реализацию алгоритмов и структур данных, которые используются в других местах. Хороший пример – BST (Binary Search Tree). Реализовав его 1 (или пару) раз "руками" начинаешь глубже понимать, как это работает, и когда читаешь про системный дизайн и видишь: "индекс в СУБД реализован при помощи BST" то понимание происходящего приходит намного быстрее и легче. Сюда же бы отнес реализацию LRU (Least Recently Used) Cache, binary search, …
Меньше "магии" в инструментах
С одной стороны, не факт, что придется работать с картами как разработчику, с другой стороны вместо "карты это магия" начинаешь видеть в них графы, и алгоритм поиска кратчайшего пути. Да и самы графы вместо букв в тетради из университета или статьи из Википедии начинают обретать вполне себе обозримый смысл.
То же самое с играми. Поиск кратчайшего пути из точки А в точку Б для вашего персонажа становится куда более понятным с точки зрения реализации.
Спортивный интерес
Здесь, пожалуй, мое личное, но все же. Это похоже на некоторое состязание для разработчиков. В принципе, можно было выбрать любую интеллектуальную дисциплину. Задачки на алгоритмы объединяют в себе разработчиков приложений/бекенда/фронтенда, и это в какой-то степени наша общая боль 🙂
Гарант дисциплины / универсальное мери́ло
Я воспринимаю это так: "если уже этот человек смог со всех сил навалиться и преуспеть в одном деле – то сможет и в другом". Можно было бы взять что угодно – шашки/спорт/вышивание… Если человек обладает достаточной упертостью и умеет фокусироваться на цели и достигать ее – он это сможет сделать в рамках вашей компании. Это очень полезное качество. Но если шашки и вышивание были бы плохим мери́лом – то навык решения алгоритмов это вполне себе подходящее место.
Шаг 1. Режим
Стоит принять, что развитие этого навыка невозможно с наскока. Нельзя навалиться со всех сил и осилить его. Несколько раз я засучив рукава пытался со всех сил взять и прокачаться. Потом я уставал, что-то случалось, смена работы, отпуск, … В итоге я мог осилить ~15 задач за год:

Привычка – вторая натура
А что если не осилить этот навык за 2 недели? И даже за месяц. А что если попробовать выделять немного времени, но каждый день? Буквально одну помидорку. Можно даже оставить в отпуске и на праздники, но делать что-то совсем простое (~5-10 минут), чтобы все-таки восстанавливаться, но при этом не потерять привычку и не "вкатываться" в режим заново.
Как работает у меня: Каждое утро я посвящаю примерно 1 помидорку на обучение за утренним кофе. Иногда чуть больше, иногда чуть меньше. В какой-то момент я решил, что прям сейчас алгоритмов достаточно, и начал посвящать эту рутину другим темам (System Design / какая-то технология конкретная / etc).
Индивидуальное позитивное подкрепление
Тут нужно найти то, что драйвит лично вас. Меня драйвила серия дней без пропусков (эдакий Duolingo-style), сначала это целых 10 дней когда я решал задачи подряд, потом это 30! Целый месяц! Так я докатился до 365 дней решения задач на Leetcode подряд. Если есть друзья, которые вас хвалят – замечательно, делитесь с ними своими продвижениями, получайте похвалу. Главное, найдите то, что вам помогает.
Мой профиль выдерживая режим:

"Keep grinding". Почему это работает
"Keep grinding" ("просто продолжай делать"). Все знают, что "без труда не выловить и рыбку из пруда", и вообще надо трудиться, но все же. За счет чего именно упорство может привести к успеху?
Типы задач не бесконечны
Когда начинаешь решать задачи, сталкиваешься с новым классом задач, потом с еще одним, потом с еще одним… И вот проходят недели, а по ощущениям их как будто бы остается бесконечное множество впереди. В этот момент очень важно себе напоминать, что они начнут повторяться. "Keep grinding". И вот как наступит тот момент, когда задачи начнут повторяться – самое сложное позади. На определенном этапе либо с 90% задача будет поддаваться сама, либо с небольшой подсказкой (которые даже на собеседованиях будут).
Что если не решил
Главная цель – узнать и понять что-то новое сегодня. Если не решили задачу – можно осилить разбор решения, либо запустить debugger на рабочем коде и прям пошагово посмотреть, как выполняется алгоритм. Еще вариант – рисовать на листочке (я прям записывал значения на каждой итерации и визуализировал стрелочками). Самое важное – это понимание. Если сегодня понимания стало больше, чем вчера – вы на верном пути.
Сначала пробуй сам
Большой соблазн читать решение, и сразу смотреть разбор. "Вот я сейчас много задач разберу, и тогда смогу решать". Здесь очень похоже на изуче��ие языков. Если вы хотите говорить на английском – слушать английский недостаточно, нужно говорить. Поэтому с задачами я рекомендую следующий подход: открываешь задачу, пытаешься решить сам. Если за 5-10 минут не получается вообще ничего – можно идти в решения и разбирать. Если получилось хоть какое-то – хорошо, теперь можно смотреть оптимальное. Если вообще получилось – ура, пожинаем плоды наших трудов.
Восприятие и насмотренность улучшается
Поначалу уровень когнитивной нагрузки при решении задач очень высок. И это нормально. Достаточно вспомнить момент первой встречи с циклами. Их буквально приходилось запускать в голове и проходить каждую итерацию. Возьмем кусок кода:
for (int i = 0; i < arrLength; i++) {
sum = sum + arr[i];
}Сегодня такие блоки кода считываются практически мгновенно, и не расходуются силы на "запуск" каждой итерации цикла в голове (Мозг упрощает знакомый паттерн практически до sum = SUM(arr) и воспринимает почти как обычный текст).
В то время как при первом знакомстве вы разбирали этот код на отдельные команды и воспринимали его примерно так:
int i = 0;
i < arrLength; // Проверяем, где же там arrLength, и какой он
i = 0 + 1; // = 1
sum = sum + arr[0];
i = 1 + 1; // = 2
sum = sum + arr[1]; Что отличает блок кода выше от блока кода ниже? Да, объем кода больше, но если написать бинарный поиск несколько раз – он станет требовать куда меньше концентрации внимания:
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}Подобная "насмотренность" приходит по всем классам задач, и если вы напишете их по нескольку раз – больше не потребуется тратить на них много сил. И эта "насмотренность" приходит со временем. Ровно так же, как она пришла с for() {}.
Тратить деньги – тоже инструмент
Когда вы платите за изучение языка вы трудитесь более усердно, чем на бесплатных курсах. Когда вы покупаете абонемент в спортзал, вы посещаете его чаще, чем бесплатный турник на улице. Этот же принцип работает и с обучением алгоритмам. Я купил подписку, получил онлайн дебаггер (очень удобно), и доступ к разбору задач. За рекламу мне, к сожалению, не платят. Этот совет чисто от себя. Но ведь действительно ли вы готовы в это вкладываться, если не готовы потратиться? Вопрос хороший.
Покупка платной подписки/книги/курса говорит вам же о том, что вы вкладываетесь в это. И вам становится в том числе жалко расходовать ресурс в пустую. В данном случае ресурс – это не только деньги, но и драгоценное время.
Лично мой опыт – после покупки платных подписок и покупки книг я точно стал вкладываться больше и находить для обучения больше времени.
Быть лучше, чем вчера
Если быть откровенным – я не чувствую, что я прям круто решаю задачи. Я ждал, что снизойдет на меня вот это ощущение "ну все, теперь я освоил этот навык раз и навсегда!". Но из объективных вещей – я действительно стал проходить эти собеседования, и я стал ощущать себя намного увереннее по обе стороны технических собеседований. Если каждый день быть лучше чем вчера – однажды станешь достаточно хорош. Даже если ты этого пока не чувствуешь :-)
