Хабр, привет! Меня зовут Владимир Михайлов, я занимаюсь бэкендом в Яндекс Такси — мы создаём внутренние продукты, которые используют в разных юнитах Яндекса. Также я работаю наставником на курсах «Разработчик C++» и «C++ для бэкенда» в Яндекс Практикуме.
А ещё я помогаю компании с наймом и провожу предварительные секции с кандидатами — разработчиками C++. Я расскажу, какие задачи даю на этих секциях, на что обращаю внимание и как подготовиться к подобному собеседованию.
Что такое предварительные секции
Когда бэкенд-разработчик откликается на вакансию в Яндексе, ему отвечает HR-менеджер, который изучает резюме кандидата и проверяет, насколько описанный в нём опыт подходит вакансии, а потом устанавливает первый контакт и оценивает софтскилы. Если разработчик прошёл проверку, его допускают к техническому собеседованию, которое состоит из нескольких этапов.
Первый из них — предварительные секции — провожу, в том числе, я. У меня есть час в Zoom, чтобы дать кандидату задачи, посмотреть на то, как он их решает, и задать дополнительные вопросы. Потом я оставляю фидбек о потенциальном сотруднике для следующего нанимающего специалиста. Я пишу, решил ли кандидат задачи и ответил ли на вопросы, насколько уверенно это сделал. Также делаю заметки о его софтскилах: насколько корректно он общался и сильно ли нервничал (особенно актуально для тех, кто впервые проходит такие секции).
Предварительные секции помогают проверить общие знания кандидата по С++, но это ещё не весь отбор. На следующих этапах тоже будут задачи, и уже сложнее.
Предварительные секции состоят из двух обязательных задач. В исключительных случаях может быть и третья задача и, если останется время, небольшая серия вопросов. Решения пишутся в онлайн-редакторе без компиляции.
Первая задача: простая, но не совсем
Обычно первую задачу я даю лёгкую, она не требует ни знания алгоритмов, ни сложных вычислений. Над ней достаточно немного подумать и аккуратно написать код.
У Яндекса есть свой пул задач для собеседований, и, к сожалению, я не могу поделиться реальным примером. Но есть похожие задачи с Leetcode. Например, на поиск дубликатов в массиве с условием.
![](https://habrastorage.org/getpro/habr/upload_files/cb0/3cd/0a6/cb03cd0a6df15f24490b78fd5ba193af.png)
Программа принимает массив с числами nums
и переменную k
, равную максимальному возможному расстоянию между одинаковыми значениями. Если условия выполняются — равные числа в nums
есть и разница их индексов меньше или равна k
, код должен выдавать true
, если нет, то false
.
Или вот — задача на выявление повторяющихся последовательностей символов в строке.
![](https://habrastorage.org/getpro/habr/upload_files/68d/79e/f41/68d79ef41576c782412b88b833cb632e.png)
Чтобы решить, нужно проверить, можно ли воссоздать заданную строку только с помощью умножения части строки, без добавления дополнительных символов.
Неожиданно, но на первой задаче люди застревают чаще всего. Хоть она и кажется очень простой и такой, в определённом смысле, является, но иногда её не могут решить и опытные разработчики. Есть такое состояние: думаешь, что всё сделал и предусмотрел, но тут тебе задают каверзный вопрос, и ты «плывёшь». Тут то же самое: кажется, что код написан и вроде всё работает, но внезапно всплывает какой-то айсберг и всё — ступор. Самое долгое решение на моей памяти заняло 55 минут из часа встречи.
Вторая задача: алгоритмы
Вторую задачу я обычно даю на алгоритмы. Её сложность зависит от того, как кандидат решил первую задачу. Если вижу, что человек путается и нервничает, то даю задание попроще. Если кандидат прошёл предыдущий этап без проблем, — посложнее.
Пример c Leetcode — решение математического примера, записанного обратной польской записью.
![](https://habrastorage.org/getpro/habr/upload_files/bf2/2b5/86e/bf22b586e173d882dcad6a9241a978a7.png)
На входе мы получаем массив из чисел и операторов. Код должен выдать результат решения.
Ещё один пример — задача про заправки.
![](https://habrastorage.org/getpro/habr/upload_files/2fa/afc/d22/2faafcd22be8d393e515bbd4ad92dd7e.png)
Мы едем по круговой трассе с заправками. На каждой заправке i
мы заливаем в бак gas[i]
бензина, а доезжая до неё, тратим cost[i]
бензина. На входе мы получаем массивы gas
и cost
, цель — узнать, с заправки с каким индексом нужно начать движение, чтобы объехать круг один раз, или вернуть -1
, если это невозможно.
Похожие примеры есть в «Тренировках по алгоритмам» от Яндекса — бесплатном курсе с лекциями, домашними заданиями и разборами ошибок.
Если остаётся время
Если кандидат легко решил обе задачи, то могу дать третью. Но какая она именно, уже не так важно — на результат встречи и мою обратную связь она не повлияет, даже если человек с ней не справится.
Также я могу задать человеку вопросы по теории. Спросить про умные указатели, многопоточность и асинхронность (что это такое, чем они отличаются и как они связаны), контейнеры (зачем нужен array
, если есть vector
?) и так далее. Но это необязательная часть интервью — всё-таки решение задач хорошо закрывает эти базовые вопросы, так как человек использует функции, контейнеры. Без знания теории у него ничего не получится.
На что я обращаю внимание
Есть несколько критериев, которые влияют на мою оценку кандидатов.
Успешность решения задач. Конечно, это самое важное. Но при этом, если что-то не получается, это не причина отсеять кандидата на предварительных секциях. Как минимум, я буду пытаться подтолкнуть кандидата к верному решению. Если вижу, что косвенно помочь не получается, могу подсказать и прямо, в каком направлении стоит размышлять и почему предлагаемое кандидатом решение неэффективно.
Даже незнание функций не является чем-то непоправимым. Может, человек идёт на минимальный грейд? В таком случае я уточню, что кандидат — потенциальный стажёр.
Стиль кода. В Яндексе вы будете работать в команде, поэтому ваш код должен быть не только рабочим, но и понятным. С этим у кандидатов бывают проблемы. Вот несколько типичных ошибок:
#include <iostream>
bool func(vector<int>& v) { // тут плохи непонятные название функции и параметра + то, что параметр передаётся по ссылке, а не по константной ссылке (но это зависит от задачи)
...
for(int i = 0; i < v.size(); i++) // тут плохо сравнение signed и unsigned (со всеми вытекающими)
{
}
...
int some_params;
...
some_params++; // нет смысла использовать постфиксный инкремент в этой ситуации
....
}
Проблема со стилем часто встречается у олимпиадников и тех, кто много решал задачи на Leetcode, но не в реальных проектах в команде.
Рассуждения. Если кандидат рассуждает вслух, прекрасно. Если нет, тоже ничего страшного, так как он всё равно проговорит решение, а я смогу задать дополнительные вопросы. Грамотное рассуждение важнее, чем решенная задача, — иногда человек правильно мыслит, проговаривает корректное решение, но не может полностью реализовать его в коде. Стоит отметить, что речь не об абсолютной неспособности решить задачу — скорее, я могу закрыть глаза на то, что кандидат не реализовал нужную, но не самую важную функцию. И если останется время, мы всё равно к ней вернёмся. Чаще всего подобные ошибки у разработчиков случаются из-за волнения, и это нормально.
Стиль общения. Идеально, если кандидат адекватно, вежливо и спокойно общается. Если он сильно нервничает, а в его голосе проступают панические нотки, это тоже нормально. Но если кандидат грубит, высказывает пренебрежение и раздражается в ответ на замечания, то я добавлю в вердикт, что общение было не очень удачное. Правда, таких разработчиков на моей памяти ещё не было.
Главный вопрос, который я задаю себе в конце каждого интервью: а хочу ли я видеть этого человека в команде? Если нет, то это главный и единственный красный флаг — я напишу об этом в итогах встречи и опишу, что именно мне не понравилось. При этом мой вердикт не будет однозначным NO HIRE, я просто поделюсь впечатлениями с рекрутером. Если честно, такие кандидаты мне ещё не встречались.
Как подготовиться к предварительным секциям в Яндексе
Собеседование — это серьёзный вызов даже для опытных разработчиков. Я рекомендую начать готовиться за неделю, потому что рабочие задачи в любом случае отличаются от задач на секциях.
В подготовку я бы включил час в день на Leetcode. Когда готовился к найму, решал две задачи Easy и одну Medium. Если понимал, что задача не даётся за 15 минут, искал готовое решение и пытался его понять и реализовать. Если вы уверенно решаете эти задания и можете решить за час две задачи Medium, то можете попробовать Hard. Но в собеседованиях такой уровень обычно не встречается.
У Leetcode есть минус для подобной подготовки — сервис показывает тест, на котором упало решение. Это приучает к безнаказанности, ведь цена ошибки на собеседовании или в настоящей рабочей задаче выше. Поэтому я советую писать код, который пройдёт проверку с первого, максимум со второго раза.
«Тренировка по алгоритмам» от Яндекса будет с вами строже — вы поймёте, что код не работает, но вам придётся самостоятельно разбираться почему. Это может сильно бесить, но это полезно.
Также полезно повторять общую теорию — например, те же вопросы о типах контейнеров встречаются во многих подборках «Популярные вопросы на собеседовании по С++».