Внутренний Я(ндекс)

в 17:54, , рубрики: Без рубрики

В этой статье я хочу описать (часть) моего опыта взаимодействия со структурой, именуемой в дальнейшем "яндекс", с точки зрения работника. Опишу собеседования и этап "входа".

Да, уже были статьи про собеседование и даже в эту же структуру, некоторые из них я видел, но не во всём с ними согласен, к тому же конкретно С++ разработчиков я там не видел.

Внутренний Я(ндекс) - 1

Начало

Это был спокойный осенний вечер, ветер играл с листьями, море начало свой вечерний танец с солнцем. Раздался звук. Это было уведомление телеграмма. Ещё одно. За ним последовал грохот всплывающего уведомления о пришедшем емейле. Это были они. они вышли на меня. 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;
    }
};

Фух, первое собеседование позади, вероятно в следующих меня ожидают вопросы по плюсам и что-то спросят про предыдущий опыт. Может даже о жизни поговорим?

Фидбек:

Внутренний Я(ндекс) - 2

Ну, усложнение это конечно давать хард с литкода на собеседовании, но удивляет тут другое

  • давай ещё одну секцию с задачами 😉

  • после этого останутся только алгоритмы ☠️

  • не уверен, что мы успеем их пройти в этом году☠️☠️☠️

То есть.. хард с литкода это были задачки, а алгоритмы они потом. После этого конечно был долгий разговор чем отличаются задачки от алгоритмов (спойлер - ничем)

Конечно, такой вызов только раззадоривает, поэтому не обращая внимания на красные флаги бежим на

Второе собеседование

После первого я порефлексировал и пришёл к нескольким выводам:

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

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

  • не решать задачи слишком легко, а то дадут сложнее

Все свои выводы я конечно проигнорировал, потому что подстраиваться под это - значит изменять своим принципам(мне лень)

Zoom. Сайт-Блокнот. Я. Собеседующий. Мы снова встретились. В этот раз был какой-то человек, которого будто по распределению отправили на окраину галактики сортировать мусор. Он был сух, просто копипастнул текст medium leetcode задачи в общий блокнот и молчал. Пытаясь разрядить обстановку я спросил что-то про задачу и аргументы(зная, что на литкоде обязательно внизу написано что-то про них). Он скопировал это тоже. Потом я просто решил задачу, объясняя что и почему я делаю, но кажется собеседующему было безразлично.

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

Задача №3

сложность: leetcode hard

Пользователи приходят, обращаются в систему, некоторые их них делают это слишком часто (считаются роботами)

Дано число K (обозначает время), число N(> N обращений за K времени означает робота) нужно написать тип с несколькими функциями, "обратиться", "количество обнаруженных роботов за такой-то период" и так далее

(формулировка может быть не точная, не сохранилась)

Тьфу-ты, опять слишком хорошо первую задачу решил.

Не идеальное по алгоритмической сложности решение не принимается(O(1) обращение например). Много времени было потрачено на то, чтобы убедить собеседующего, что как-то невозможным выглядит это требование, там максимум ожидаемое O(1*) в среднем.

Попыхтел, но сделал, получилось что-то похожее на LRU кеш по строению, список и хеш мапа, плюс всякие мелочи и хаки. Время конечно поджимало, что же в итоге?

Фидбек:

Внутренний Я(ндекс) - 3

Да, код сыроватый, ему всего 15 минут 32 секунды от рождения. Нужно было выделить общий код... (я дважды написал одну строку с erase), что же, сожалею, не прочитал мысли и не написал прямо как в листочке ответов у собеседующего, в следующий раз зайду таки на экстрасенс-литкод и подготовлюсь лучше

Итого: medium + hard литкод как вы помните это всего лишь задачки. На очереди алгоритмы.

Третье собеседование

Этим этапом пугали всех, даже самые смелые заходили таки на литкод, чтобы подготовиться. Я тоже подготовился, две недели праздновал праздники и отдыхал, не прикасаясь к коду(мы называли это новый год).

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

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

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

Я понял, это был тест на знание алгоритмической сложности. Если бы я продолжал его перебивать, то он читал бы O(N^2) времени, что забрало бы у меня время на решение самих задач.

Чтение сухой инструкции заняло около 7 минут, потом он поприветствовал меня и задал самый сложный вопрос из всех, я даже не мог его представить. Он был неожиданным, к нему не подготовился бы никто и яндекс знал это:

- Вы же будете писать на JavaScript?

Чудом и усилием воли я выдержал этот тест и не засмеялся, ответил что буду писать на С++, на что собеседующий заявил, что его не знает, поэтому "нам будет сложно". А ведь сложно и обещали, не соврали.

Задача №4

Сложность: medium ?

Дан массив из нулей и единиц. Нужно определить, какой максимальный по длине подинтервал единиц можно получить, удалив ровно один элемент массива.

Требования: O(1) по памяти, O(N) по времени

Я спокойно преступил к решению, но собеседующий постоянно перебивал меня, потому что не понимал что означают конструкции С++. Поэтому это вылилось в просто лекцию по С++ во время которой мы прошлись по концепции итераторов, алгоритмов, контейнеров, которая мне даже понравилась. А потом я написал

size_t c = std::count(/*что-то там*/);

На что последовало резкое "а можно поближе к железу?". Голова пошла кругом, мир начал рушиться, мои объяснения не были поняты... Как преподаватель я был угнетён.

С горем пополам, задача была решена на общем подмножестве JavaScript и С++, который можно назвать Y++

На вторую задачу(почему-то) времени не хватило

Фидбек(спустя неделю):

Внутренний Я(ндекс) - 4

Вот жеж! Даже на алгоритмах всё время ушло на одну задачу! Попались.

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

Но это ещё не весь фидбек:

шутка

шутка

Шучу, на самом деле вот:

Внутренний Я(ндекс) - 6

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

На выбор было неважно что и КомандаРоботов:

Внутренний Я(ндекс) - 7

Я подробно рассмотрел эту возможность и взяв волю в кулак решил, что

я не робот

и меня не поймут в команде роботов (из которой видимо был последний собеседующий)

Перед тем как продолжать, давайте посчитаем вероятность гипотетического олимпиадника стать роботом (пройти в их команду)

  • 1 легкая, 2 медиум, 2 сложные задачи + если смотреть на тенденцию ещё одна сложная задача в третьем собеседовании после первой

  • наш олимпиадник идеален, его вероятность решить лёгкую задачу за 30 минут 100%, вероятность решить среднюю 90%, вероятность решить сложную 80%

    1 * 0.9 * 0.9 * 0.8 * 0.8 * 0.8 (три сложных, две средних, одна лёгкая, одна ошибка - вылет) получается примерно 40%. Получается даже такой гений просто надеется на удачу и хорошо выпавшие задачки?

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

Итак, документы подписаны, алгоритмы позади (вместе с задачками). Так как на своём ноутбуке работать небезопасно, за пару дней до переезда мне вручили ноутбук, а выглядел он примерно так:

Внутренний Я(ндекс) - 8

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

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

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

Выводы

Описанное собеседование не проверяет ничего из реальных навыков, более того, оно даже не проверяет знание алгоритмов. В коде потом я не раз встречал вопиющие примеры плохих алгоритмов, например поиск общего подмножества за O(N^3)

Можно сколько угодно рассуждать о том, что "если человек понимает алгоритмы, то он научится и писать на Go/Python/C++", но это не работает. В лучшем случае на обучение уйдёт немало времени(и багов), в худшем человек так и не осилит С++, причём будет думать, что раз он бинарный поиск на питоне решил, то и С++ он отлично знает. Порой казалось, что для написания на новом языке люди используют ChatGPT, причём впечатление очень сильное

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

Остальные выводы делайте сами

Автор:
Kelbon

Источник

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


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