В этой статье я хочу описать (часть) моего опыта взаимодействия со структурой, именуемой в дальнейшем "яндекс", с точки зрения работника. Опишу собеседования и этап "входа".
Да, уже были статьи про собеседование и даже в эту же структуру, некоторые из них я видел, но не во всём с ними согласен, к тому же конкретно С++ разработчиков я там не видел.
Начало
Это был спокойный осенний вечер, ветер играл с листьями, море начало свой вечерний танец с солнцем. Раздался звук. Это было уведомление телеграмма. Ещё одно. За ним последовал грохот всплывающего уведомления о пришедшем емейле. Это были они. Они вышли на меня. HR'ы яндекса. Их условие было простым - приди на собеседование. Что ж, была не была, попробуем, подумал я и мы договорились встретиться в Zoom.
Как оказалось позже, ставка была ложной, HR система яндекса не так проста, налицо системный подход к безопасности. Каждый HR автономен и не имеет доступа ко всей информации. Даже если главный центр будет уничтожен, каждый из них будет пытаться воссоздать компанию с нуля. Вдохновлялись явно природой.
Поэтому договориться нужно с каждым и даже когда вы работаете в яндексе они вам всё равно пишут.
Мне были любезно предоставлены подготовительные материалы: ссылка на литкод и время.
В свою очередь я добросовестно не открывал эту ссылку, потому что готовиться к собеседованию это и обман самого себя и компании (мне лень), хотя я отлично понимаю тех, кто пытается эту систему обмануть, если она порочна (собеседование не связано с реальной работой)
Первое собеседование
И вот мы уже в Zoom, собеседующий был очень добродушным и приятным в общении - он поздоровался, дал ссылку на пустой блокнотик для кода и разминочную задачку.
Задача №0
сложность: leetcode easy
Вернуть массив k наиболее часто встречающихся элементов данного массиваПричём в массиве всегда хотя бы k элементов, а k > 0, после уточнения: порядок одинаково частых элементов неважен, дубликаты не убирать
И сходу я написал примерно следующее (сейчас уже точно не упомнить):
std::vector<int> most_freq(std::span<const int> nums, int k) {
assert(k <= size(nums) && k >= 0);
std::unordered_map<int, size_t> counts;
for (int x : nums) ++counts[x];
std::vector<int> out(k);
auto to_freq_proj = [&] (int x) { return counts[x]; };
std::ranges::partial_sort_copy(nums, out, std::greater{}, to_freq_proj);
return out;
}
Собеседующий был явно ошарашен, но принял решение
Так как я решил задачу быстро и по оценке собеседующего хорошо, решено было дать мне задачу повышенной сложности. Логику этого решения я объясняю ?.. отсеиванием слишком квалифицированных сотрудников?..
Задача №1
сложность: leetcode hard
Даны высоты столбиков, посчитать сколько воды могло бы собраться в этих столбиках в дождь (подробнее на литкоде по ссылке https://leetcode.com/problems/trapping-rain-water/)
Немного пришлось подумать конечно, но в итоге я придумал алгоритм за O(N) по времени и O(1) по памяти и написал его, а потом принялся за самое сложное - доказать собеседующему, что решить с такой сложностью возможно. Но собеседующий был приятный и в беседе мы продебажили код и разобрали крайние случаи
Решение у меня сохранилось, так как я прямо после собеседования пошёл и вставил его как было в литкод, чтобы убедится в его правильности
решение (сигнатура литкода сохранена)
class Solution {
public:
int trap(vector<int>& vec) {
if(vec.size() < 2)
return 0;
auto max_it = std::max_element(begin(vec), end(vec));
int max_height = *max_it;
int max_water = vec.size() * max_height;
max_water -= std::accumulate(begin(vec), end(vec), 0);
auto go = [&] (auto it, auto e) {
int count = 0;
int cur_max = *it;
++it;
while(it != e) {
++count;
if(*it >= cur_max) {
max_water -= count * (max_height - cur_max);
cur_max = *it;
count = 0;
}
++it;
}
};
go(begin(vec), max_it == end(vec) ? max_it : std::next(max_it));
go(rbegin(vec),
max_it == begin(vec) ?
std::reverse_iterator(max_it) : std::next(std::reverse_iterator(max_it)));
return max_water;
}
};
Фух, первое собеседование позади, вероятно в следующих меня ожидают вопросы по плюсам и что-то спросят про предыдущий опыт. Может даже о жизни поговорим?
Фидбек:
Ну, усложнение это конечно давать хард с литкода на собеседовании, но удивляет тут другое
давай ещё одну секцию с задачами 😉
после этого останутся только алгоритмы ☠️
не уверен, что мы успеем их пройти в этом году☠️☠️☠️
То есть.. хард с литкода это были задачки, а алгоритмы они потом. После этого конечно был долгий разговор чем отличаются задачки от алгоритмов (спойлер - ничем)
Конечно, такой вызов только раззадоривает, поэтому не обращая внимания на красные флаги бежим на
Второе собеседование
После первого я порефлексировал и пришёл к нескольким выводам:
писать хороший код невыгодно, его поймут. А если написать приемлемо непонятный код и очень уверенно говорить, что он работает, собеседующий не сможет продебажить его в голове и согласится
собеседующим плевать, они не знают обо мне ничего. Даже на каком языке я собираюсь писать
не решать задачи слишком легко, а то дадут сложнее
Все свои выводы я конечно проигнорировал, потому что подстраиваться под это - значит изменять своим принципам (мне лень).
Zoom. Сайт-Блокнот. Я. Собеседующий. Мы снова встретились. В этот раз был какой-то человек, которого будто по распределению отправили на окраину галактики сортировать мусор. Он был сух, просто копипастнул текст medium leetcode задачи в общий блокнот и молчал. Пытаясь разрядить обстановку я спросил что-то про задачу и аргументы (зная, что на литкоде обязательно внизу написано что-то про них). Он скопировал это тоже. Потом я просто решил задачу, объясняя что и почему я делаю, но кажется собеседующему было безразлично.
Задача решена, значит можно дать следующую, так что он просто снова скопировал её текст в блокнот. На лице его промелькнула ухмылка.
Задача №3
сложность: leetcode hard
Пользователи приходят, обращаются в систему, некоторые их них делают это слишком часто (считаются роботами)
Дано число K (обозначает время), число N(> N обращений за K времени означает робота) нужно написать тип с несколькими функциями, "обратиться", "количество обнаруженных роботов за такой-то период" и так далее
(формулировка может быть не точная, не сохранилась)
Тьфу-ты, опять слишком хорошо первую задачу решил.
Не идеальное по алгоритмической сложности решение не принимается(O(1) обращение например). Много времени было потрачено на то, чтобы убедить собеседующего, что как-то невозможным выглядит это требование, там максимум ожидаемое O(1*) в среднем.
Попыхтел, но сделал, получилось что-то похожее на LRU кеш по строению, список и хеш мапа, плюс всякие мелочи и хаки. Время конечно поджимало, что же в итоге?
Фидбек:
Да, код сыроватый, ему всего 15 минут 32 секунды от рождения. Нужно было выделить общий код... (я дважды написал одну строку с erase), что же, сожалею, не прочитал мысли и не написал прямо как в листочке ответов у собеседующего, в следующий раз зайду таки на экстрасенс-литкод и подготовлюсь лучше
Итого: medium + hard литкод как вы помните это всего лишь задачки. На очереди алгоритмы.
Третье собеседование
Этим этапом пугали всех, даже самые смелые заходили таки на литкод, чтобы подготовиться. Я тоже подготовился, две недели праздновал праздники и отдыхал, не прикасаясь к коду (мы называли это новый год).
Яндекс тоже готовился. На поиски собеседующего были брошены немалые силы, бой должен был быть зрелищным.
Они обещали, что это будет сложно и это было сложно. Собеседующий, сидящий подобно роботу исключительно прямо и глядя в бумагу, не совершая ни одного лишнего движения пододвинул к себе листок и стал читать..
инструкцию о том, как будет проводиться интервью. Наконец на третьем собеседовании мне открыли эту тайну. Пока я недоумевал, он успел прочитать два предложения, я вежливо его перебил, намекая, что уже знаю. Он сказал просто: мы должны это сделать. И начал читать сначала.
Я понял, это был тест на знание алгоритмической сложности. Если бы я продолжал его перебивать, то он читал бы O(N^2) времени, что забрало бы у меня время на решение самих задач.
Чтение сухой инструкции заняло около 7 минут, потом он поприветствовал меня и задал самый сложный вопрос из всех, я даже не мог его представить. Он был неожиданным, к нему не подготовился бы никто и яндекс знал это:
- Вы же будете писать на JavaScript?
Чудом и усилием воли я выдержал этот тест и не засмеялся, ответил что буду писать на С++, на что собеседующий заявил, что его не знает, поэтому "нам будет сложно". А ведь сложно и обещали, не соврали.
Задача №4
Сложность: medium ?
Дан массив из нулей и единиц. Нужно определить, какой максимальный по длине подинтервал единиц можно получить, удалив ровно один элемент массива.
Требования: O(1) по памяти, O(N) по времени
Я спокойно приступил к решению, но собеседующий постоянно перебивал меня, потому что не понимал, что означают конструкции С++. Поэтому всё вылилось в лекцию по С++, во время которой мы прошлись по концепции итераторов, алгоритмов, контейнеров - и лекция мне даже понравилась. А потом я написал
size_t c = std::count(/*что-то там*/);
На что последовало резкое "а можно поближе к железу?". Голова пошла кругом, мир начал рушиться, мои объяснения не были поняты... Как преподаватель я был угнетён.
С горем пополам, задача была решена на общем подмножестве JavaScript и С++, который можно назвать Y++.
На вторую задачу (почему-то) времени не хватило.
Фидбек (спустя неделю):
Вот жеж! Даже на алгоритмах всё время ушло на одну задачу! Попались.
Итого, мы выяснили, что не решение одной задачи делает весь процесс проваленным. Запомним это для кое-чего в будущем
Но это ещё не весь фидбек:
Шучу, на самом деле вот:
Почему бы нет, интересно куда готовы взять дурачка, который всего лишь решил 1 легкую, 2 средних и 2 хард задачи в сумме за полтора часа.
На выбор было неважно что и КомандаРоботов:
Я подробно рассмотрел эту возможность и взяв волю в кулак решил, что
я не робот
и меня не поймут в команде роботов (из которой видимо был последний собеседующий)
Перед тем как продолжать, давайте посчитаем вероятность гипотетического олимпиадника стать роботом (пройти в их команду)
1 легкая, 2 медиум, 2 сложные задачи + если смотреть на тенденцию ещё одна сложная задача в третьем собеседовании после первой
наш олимпиадник идеален, его вероятность решить лёгкую задачу за 30 минут 100%, вероятность решить среднюю 90%, вероятность решить сложную 80%
1 * 0.9 * 0.9 * 0.8 * 0.8 * 0.8 (три сложных, две средних, одна лёгкая, одна ошибка - вылет) получается примерно 40%. Получается даже такой гений просто надеется на удачу и хорошо выпавшие задачки?
Ладно, от скучных расчётов пойдём дальше, во вторую команду не требовалось ничего и я пошёл туда. Причём условием был переезд в другую страну, но я тот ещё путешественник, поэтому согласился.
Итак, документы подписаны, алгоритмы позади (вместе с задачками). Так как на своём ноутбуке работать небезопасно, за пару дней до переезда мне вручили ноутбук, а выглядел он примерно так:
В комплекте шли крошки на клавиатуре, а также требование отпечатка пальца некой Татьяны для разблокирования. Что ж, всякое в логистике бывает. Поэтому я полетел с ним и решил на месте поменять на что-то другое
Снова ветерок, новая страна, яркие впечатления, местная кухня... Иду к офису, встречать свой первый рабочий день в обнимку с любимым уже кирпичом, с которым мы и через дождь и через аэропорт и погрузку на самолёт с просьбой разблокировать его, потому что он уж слишком подозрительный (пальца Татьяны у меня не оказалось, но думаю это было бы ещё подозрительнее).
Вхожу, снимаю куртку и вешаю её, переступая человека с ноутбуком на полу (места нет), подыскиваю себе с кирпичом свободное место и знакомлюсь с командой... В которой нет никого, кто пишет не на Python.
Выводы
Описанное собеседование не проверяет ничего из реальных навыков, более того, оно даже не проверяет знание алгоритмов. В коде потом я не раз встречал вопиющие примеры плохих алгоритмов, например поиск общего подмножества за O(N^3)
Можно сколько угодно рассуждать о том, что "если человек понимает алгоритмы, то он научится и писать на Go/Python/C++", но это не работает. В лучшем случае на обучение уйдёт немало времени (и багов), в худшем человек так и не осилит С++, причём будет думать, что раз он бинарный поиск на питоне решил, то и С++ он отлично знает. Порой казалось, что для написания на новом языке люди используют ChatGPT, причём впечатление очень сильное
Также собеседование не проверяет коммуникативных навыков и банально тот факт, что человек то адекватный и хороший, впечатление, что собеседующие никак не мотивированы, причём вероятно сознательно, в целях какой-то безопасности
Остальные выводы делайте сами.