Как задачи на LeetCode прокачали меня как разработчика, или по-честному про алгоритмы

в 10:13, , рубрики: Без рубрики

Перевод статьи «How a year-long LeetCode habit upped my professional game» из блога Злых марсиан.

Культ лайвкодинга и алгоритмических задач процветает до сих пор. Вопросы в стиле «как преобразовать бинарное дерево» или «как написать пирамидальную сортировку» регулярно встречаются на собеседованиях не только в бигтехе — хотя это и не те задачи, которые каждый день решает среднестатистический разработчик. Из-за этого многие программисты начинают искренне ненавидеть алгоритмы.

Однажды я зашла на LeetCode, одну из популярных платформ для решения алгоритмических задач. Сразу уточню: мне не нужно было готовиться к собеседованию, и моя работа не требовала продвинутого знания алгоритмов. Тем не менее я заметила, что у меня стали заполняться пробелы в знаниях, и я продолжила решать задачи — каждый день понемногу.

С тех пор у меня накопилось более 400 решённых задач на LeetCode. Теперь я уверена, что такие платформы как LeetCode, HackerRank или CodeWars, при правильном подходе, способны поднять профессиональные навыки любого разработчика на новый уровень.

Вот чему я научилась за год ежедневного решения задач:

  1. В моём коде стало меньше багов. Навык самопроверки улучшился, появилась привычка думать об ограничениях и пессимистичных сценариях;

  2. При этом заметно увеличилась скорость написания кода. Многие вещи теперь делаются на «автомате»;

  3. Я больше не боюсь сложных рабочих задач;

  4. Я научилась качественнее объяснять свои решения и больше думать о чистоте кода;

  5. Мой уровень самодисциплины возрос.

Но обо всём по порядку.

Как задачи на LeetCode прокачали меня как разработчика, или по-честному про алгоритмы - 1

1. Больше внимательности, меньше багов

Привычка думать о случаях, в которых написанный тобой код «сломается», – очень полезна для разработчиков.

Я люблю LeetCode за то, что он мягко заставляет тебя если не писать, то хотя бы мысленно просчитывать разные тестовые сценарии. Перед тем, как принять решение задачи, платформа всегда проверяет его по многочисленным тестам.

Может случиться так, что падает всего один сценарий из сорока, и он вынуждает тебя переписывать половину твоего кода. Это может сильно раздражать. Да и в целом видеть после отправки решения грустные красные буквы «Wrong Answer» – удовольствие ниже среднего. Особенно если задача сложная.

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

Особенно приятно то, что с течением времени это стало проявляться не только при решении алгоритмических задач, но и на моей работе, а также при написании собственных проектов. Как правило, в обычной рабочей атмосфере нам не высвечиваются слова «Wrong Answer», когда мы допустили ошибку — это всплывает позднее в виде бага у клиента.

Поэтому задаваться вопросами в духе «упадёт ли моя функция, если входные данные были очень большие или, наоборот, пустые» – отличная привычка. Тренировка на коротких алгоритмических задачах помогает развить её лучше всего.

Что ещё поможет, чтобы наработать внимательность и делать меньше ошибок?

  • Обращать внимание, как те или иные ограничения в задаче влияют на предполагаемое решение. Например, если в массиве может быть миллиард элементов, то решение брутфорсом вряд ли подойдёт;

  • Анализировать, насколько велика сложность решения по времени и по памяти, используя нотацию «О» большое. Не стоит обращать внимание на процент «успешности» времени выполнения кода, который показывает Leetcode после отправки. Он бесполезен; в этой статье подробно рассказывается, почему это так;

  • Всегда помнить про пессимистичные сценарии, а не только про общие.

2. Скорость написания кода растёт, решения изобретаются быстрее

Я не ожидала этого, но с приятным удивлением заметила через полгода: у меня стало уходить примерно в 1.5 раза меньше времени на задачу по сравнению с тем, когда я начинала.

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

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

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

Вот мои советы по развитию скорости:

  • Осваивайте темы в комфортном для себя темпе, переходите к следующей, только когда вы уже чувствуете уверенность в текущей. Например, сначала прорешайте 7 лёгких задач на деревья, 10 средних и 4 сложных, и только затем переходите, например, к спискам. Я не советую брать каждый день случайные задачи, поскольку это не позволяет сфокусироваться на освоении конкретной темы;

  • Не забывайте повторять старые темы. Даже если вы освоили тему деревьев, выполняйте задание по ним каждые пару недель;

  • Попробуйте решить лёгкую для себя задачу, но введя ограничение по времени, – например, десять минут. Иногда создание искусственной нехватки времени может заметно увеличить продуктивность.

3. Прививка от страха перед сложными задачами

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

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

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

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

Например, сейчас я совершенно не задумываюсь, как работают встроенные методы в JS: что возвращает .push(), или мутируют ли исходный массив методы .slice() или .splice(). Эти знания нельзя назвать алгоритмическими, однако регулярное решение LeetCode помогает твёрдо их усвоить.

Вот как можно начать чувствовать себя намного увереннее независимо от уровня сложности задачи:

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

  • Не забывайте пробовать применять полученные знания на работе ('use it or you lose it'). Например, когда это уместно и имеет смысл, попробуйте использовать структуру данных Set вместо Array;

  • Если вы только осваиваете новый язык программирования, то простейшие задачи хорошо помогают с этим. Вы поймёте синтаксис и особенности языка намного быстрее, чем если бы просто читали теорию.

4. Почва для искусства объяснения решений и чистого кода

Пару раз я натыкалась на критику, что сайты вроде LeetCode плохи тем, что они позволяют писать код как угодно грязно, лишь бы он работал. Это верно; но приучение разработчика писать чисто и не является их основной целью.

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

Так выглядит раздел с опубликованными решениями

Так выглядит раздел с опубликованными решениями

Когда я начала прояснять непонятные задачи, вчитываясь в решения и объяснения опытных разработчиков, мой процесс обучения пошёл в гору. Я и сама попробовала выкладывать собственные решения. К тому времени я поняла, что людям полезно, когда решения объяснены кратко, но ясно.

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

Так как же улучшить навык чистого кода и объяснения решений, пользуясь LeetCode?

  • Не стесняйтесь публиковать свои решения, даже если они не уникальны (только сначала постарайтесь максимально почистить код);

  • Потренируйтесь писать объяснения своих решений. Постарайтесь формулировать их так, чтобы всё понял даже новичок;

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

5. Почва для искусства объяснения решений и чистого кода

В любом деле важна мотивация и регулярность, будь то вышивание, занятия спортом или решение алгоритмических задач. Если мотивация заниматься на LeetCode уже появилась – из-за желания получить работу мечты или из-за чего-то ещё — то дело остаётся за регулярностью.

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

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

Несколько советов, чтобы сохранять мотивацию для достижения регулярности (без неё никуда):

  • Не пытайтесь каждый день решать много сложных задач, вы просто быстро выгорите. Постепенно увеличивайте сложность и уделяйте задачам определенное время (например, сорок минут в день);

  • Отслеживайте свой прогресс. Вы можете вести календарь и отмечать каждый день, когда садились за решение задач. Когда мотивация угасает, посмотрите, как далеко вы уже продвинулись;

  • Никогда не сравнивайте себя с другими. Чье-то опубликованное решение может выглядеть намного лучше вашего, но как узнать, сколько лет этот программист потратил на изучение алгоритмов?

  • Ежедневно хвалите себя: как только вы начинаете день, вы уже начинаете знать немного больше, чем вчера.

Подводя итоги. Чему же я всё-таки научилась?

За год на LeetCode я поняла, что алгоритмические задачи – не панацея, но отличные помощники. Они способны привить автоматизм при написании рутинного кода, убрать страх трудностей, приучить думать о разных тестовых сценариях. Публикация решений, с учётом старания сделать их чистыми и детальными, позволяет прокачать навык объяснения своего кода.

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

Всё ещё сомневаетесь? Просто попробуйте решить первую задачу сегодня.

Автор: Nina Torgunakova

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js