Что спрашивают на собеседованиях в IT-компании

16.09.2020

В этом посте я попробую описать, что обычно стоит ожидать на собеседованиях на позицию программиста (разработчика) в IT-компании, а также какое материалы с алгопрога и не только вам будут полезны. Пост в основном ориентирован на «студентов и старше», занимающихся на алгопроге, но и школьникам тоже будет полезно знать на будущее.

Я буду говорить, в первую очередь, про позицию, должность, разработчика на C++ (поскольку у меня больше всего опыта именно в таких собеседованиях); насколько я понимаю, собеседования на другие «серверные» языки типа Java (не андроид) или питона концептуально не сильно отличаются от того, что я буду излагать ниже, собеседования же на более «клиентские» языки типа андроид-Java или Swift или того же Javascript могут требовать существенно бОльших знаний соответствующих конкретных технологий.

По уровню я буду говорить в первую очередь про младшего или «среднего» разработчика. Формат отбора на более младшую должность (стажера), кажется, заметно более варьируется от компании к компании (хотя в общих чертах все то же, что я излагаю ниже); формат отбора на более старшие должности может включать таже дополнительные темы типа глобальной архитектуры приложения или сервиса и т.д. (но если вы претендуете на старшего разработчика, то скорее всего вы и так понимаете, чего будут от вас хотеть :) ). Про отбор на руководящие должности (менеджеров, тимлидов и т.п.) я ничего не знаю.

В разных компаниях, а нередко и в разных командах, формат собеседования, конечно, разный. Встречаются тестовые задания, когда вам надо за несколько дней написать сравнительно большой объем кода (хотя лично имхо это не очень адекватно). Встречаются знаменитые логические задачи типа «сколько бейсбольных мячей влезет в школьный автобус» (но это последнее время вроде уже не так популярно). Могут быть и другие варианты. Вообще, как правило, до реального собеседования вы будете общаться с кем-нибудь из рекрутеров, крайне полезно у них заранее уточнить, что вас будут спрашивать на собеседовании.

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

Но все-таки наиболее типичные собеседования обычно проходят по трем направлениям.

Во-первых, это беседы на общекомпьютерные и общепрограммистские темы. Типа там как работает процессор, что такое регистры, как устроена файловая система, как устроена сеть, какие-нибудь основы баз данных и т.д. Классические вопросы — чем отличается TCP от UDP, или чем отличается процесс от потока, или чем отличаются символьные ссылки от жестких ссылок в файловой системе. (Это в общем-то достаточно простые и очень баянистые вопросы, могут и что-нибудь посложнее спрашивать.) Сюда же можно отнести разговоры на теоретические темы, типа какая сложность у сортировки пузырьком или быстрой сортировки (quicksort’а). Если речь идет про позиции младших или «средних» разработчиков, и работа не будет непосредственно в деталях связана с соответствующей темой, то обычно очень глубоких знаний тут не ожидают. Вам надо иметь общее представление, понимать, как это влияет на вашу конкретную работу, но например не обязательно понимать, чем отличается набор регистров в разных моделях процессоров, или уметь писать quicksort наизусть.

Во-вторых, это вопросы по конкретным языкам программирования и технологиям, которые вы будете использовать в работе. Типа там про умные указатели в C++ (тоже баян); также, как я уже писал выше, при собеседовании на более «клиентские» языки вас могут тут намного больше и глубже спрашивать, например, про какие-нибудь особенности андроида. Здесь, конечно, от вас обычно будут ожидать более подробных знаний, чем в предыдущем пункте. Во-первых, и по синтаксису и по стандартной библиотеке (все-таки подразумевается, что вы пишете код на этом языке, значит вы должны его довольно неплохо знать). Во-вторых, в любом языке есть ряд более концептуальных, что ли, тем — например, если вы собеседуетесь на «среднего» разработчика C++, то наверное вы должны бы понимать, что такое undefined behavior и что такое инвалидация итераторов. (Для младшего разработчика это, может быть, и не так нужно.) Сюда же можно отнести концепции ООП и смежные темы, всякие там design patterns и т.д.

И в-третьих, это разного рода задачи, в которых вам надо написать сравнительно небольшой фрагмент кода, как правило, функцию или класс, которые делают то, что требуется. Во многих компаниях, особенно в крупных, именно такие задачи являются основным, что вас будут спрашивать, и к ним важнее всего тщательно подготовиться. От вас требуется понять, что надо сделать, и написать соответствующий код, особо обращая внимание на алгоритмическую корректность — чтобы правильно учесть разные крайние случаи, не зациклиться и т.д. При этом зачастую от вас не будут требовать 100% синтаксически корректного кода, не будут требовать, чтобы вы помнили интерфейсы всех структур или все методы стандартной бибилиотеки, которые вы будете использовать, важнее понимать, что именно вам надо и как вы это будете использовать.

Я бы выделил тут два основных класса задач: задачи на то, чтобы собрать алгоритм из стандартных классов и задачи на то, чтобы придумать алгоритм. В первых задачах основная сложность даже не придумать алгоритм, а понять, какие стандартные структуры вам потребуются и как в них хранить и обновлять нужную информацию. Относительно неплохой иллюстрацией такой задачи может служить задача Тупики с алгопрога — если ее решать без самописных структур данных, а также отчасти задачи из темы про STL (хотя на момент написания этого поста там не самый лучший набор задач, в этих задачах не надо особо придумывать, как именно применить структуру). Второй тип задач наиболее близок к основной массе задач с алгопрога; собственно, многие задачи с уровня 1Г, те же Сережа и лесенка, Сортировка вагонов, да и другие (за исключением самых простых) являются неплохой иллюстрацией таких алгоритмических задач.

Уровень 1Г я тут упоминаю не случайно, собственно, наиболее типичные задачи на собеседованиях не требуют какой-то хитрой теории, хитрых алгоритмов или структур данных, и по сложности примерно соответствуют уровню 1Г. Но могут встречаться и более продвинутые темы. В первую очередь это алгоритмы, или даже не алгоритмы, а скорее идеи, до которых, чисто теоретически, вы можете додуматься и самостоятельно — два указателя, сортировка событий, простое ДП, префиксные суммы, какая-нибудь рекурсия, как простая, так и рекурсивный перебор, возможно, несложная жадность и т.п. Кроме того, есть ряд популярных «академических» тем, которые обычно входят в классические университетские курсы и потому тоже бывают популярны на собеседования — связные списки, бинарные деревья, стек-дек-очередь, реже бинарный поиск, всякие обходы и поиски пути на графах (в глубину, в ширину, Дейкстра), возможно, геометрия. (Последние темы, хоть и возможны, но все-таки относительно маловероятны.) (Конечно, если для вашей работы будет нужна какая-то конкретная теория, то ее могут спрашивать активнее; например, если вы собеседуетесь на позицию, где вам надо будет работать с графикой и т.п., то наверное вас будут активно спрашивать по геометрии и т.п.) Продвинутые темы типа декартовых деревьев или допустим алгоритма Кнута-Морриса-Пратта почти наверняка вас спрашивать не будут (более того, бывает так, что дают задачу, которая решается продвинутым алгоритмом, но собеседующего вполне устроит и более простое решение).

* * *

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

Ну, во-первых, по алгопрогу. Я советую вам как минимум пройти первые 3-5 уровней, а также отдельные, упомянутые выше, темы с более высоких уровней. (В первую очередь бинарные деревья — на алгопроге они достаточно высоко, потому что, что на олимпиадах, что в реальной жизни они употребляются редко, но на собеседованиях любят спрашивать.) И надо уметь уверенно и без ошибок писать код, причем чистый код — лучше не знать крутые алгоритмы, но уметь в простых задачах написать чистый и надежный код, и в крайнем случае написать код по устному описанию алгоритма, чем знать крутые алгоритмы, но писать их просто наизусть и не уметь сделать минимальные модификации.

Во-вторых, надо достаточно хорошо разбираться в вашем языке программирования, и более широко — в технологиях, которые вы используете (особенно если речь идет про «клиентские» языки программирования). Причем имхо важнее не просто заучивать справочник наизусть, а разбираться, как оно концептуально устроено внутри; в плане фич языка и стандартной библиотеки, например, полезно хотя бы в общих чертах понимать, какие структуры данных и алгоритмы лежат в основе тех или иных классов или функций. Это вам позволит говорить типа «я не помню, как называется такой-то метод, но я думаю, он должен существовать» — имхо это намного круче, чем просто выученные наизусть интерфейсы из справки, потому что свидетельствует о том, что человек понимает, чем он пользуется. В качестве простейшего примера — вы будете понимать, что у std::set есть метод, проверяющий, есть ли в нем конкретный элемент, а у std::vector — нет, даже если вы не помните наизусть интерфейсы этих классов; в качестве более сложного — что у того же std::set нет метода получения элемента по индексу (потому что чтобы в бинарном дереве поиска уметь быстро искать по индексу, надо в вершинах хранить размеры поддеревьев, а std::set этого конечно не делает; обратите внимание, что это аргументация не уровня «я заучил справочник наизусть», а уровня «я понимаю, как это устроено внутри, и понимаю, чего можно ожидать, а чего нет», имхо это намного важнее). Разбирайтесь не только в стандартной библиотеке, но и в более глубоких идея, концепциях языка. Также надо, конечно, разбираться в ООП и хотя бы основах архитектуры программ (типа как выделять классы/функции и т.д.) При этом, конечно, если вы действительно много пишете на своем языке, то скорее всего вы уже многое и так знаете.

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

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

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

* * *

Напоследок еще раз повторю, что система проведения собеседований сильно варьируется от компании к компании. В частности, и это важно понимать, бывают довольно неадекватные компании с неадекватными форматами. Однажды я собеседовался (по скайпу) в какую-то европейскую компанию, и меня стали активно гонять по стандартной библиотеке C++, по тому, как конкретно называются разные методы у разных STL-классов, какие параметры они принимают и т.д. На мой взгляд, это совершенно неадекватно, потому что в реальной жизни у вас всегда есть справка, тот же cppreference, где всё это описано. Важно понимать, что в целом умеет та или иная структура, какие методы у нее можно ожидать, какие параметры им могут требоваться (про что я уже писал выше), а конкретные названия функций, конкретные их перегрузки и т.д. имхо знать вовсе не обязательно.

Другой пример неадекватности, многократно упоминаемый в разных блогах — когда вас пытается оценивать не профессионал, а кто-то другой, чаще всего рекрутер. Вас могут еще до реального собеседования опрашивать по анкете типа «знаете ли вы C++», «знаете ли вы git» и т.д.; могут даже пытаться задавать какие-нибудь более хитрые вопросы (типа того же «какие умные указатели в C++ вы знаете»). В целом это может быть и не так плохо, если это используется для отсева совсем уж слабых кандидатов, но когда ваши ответы начинает серьезно оценивать человек, который сам в этом разбирается довольно плохо — это конечно не дело. Или например когда тот же рекрутер пытается за вас решать, что вам будет интересно, а что нет. Пример — я собеседовался в одну компанию, вроде нормально прошел собеседование, через пару дней мне позвонила рекрутер со словами: да, нам все понравилось, но к сожалению у нас сейчас нет позиций, которые были бы вам интересны, я, мол, перезвоню через неделю. Я сказал, мол, хорошо — я тогда не особо стремился менять местро работы. Рекрутер звонила мне еще несколько раз примерно с теми же словами, потом звонить перестала. Через некоторое время я от третьих лиц узнал, что по мнению этой компании я отказался сам o_O…

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

* * *

Ну и да, если вы соберетесь собеседоваться в Яндекс, то напишите мне — я вас с радостью порекомендую (это, конечно, относится к тем людям, кого я знаю, в первую очередь, но не только, к тем, кто занимается на алгопроге).


Мой курс по алгоритмическому программированию (и подготовке к олимпиадам) для школьников, студентов и всех желающих — algoprog.ru