Небольшое вступление

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

Сразу предупрежу, по вполне понятным причинам условий задач я вам не скажу, но будет их общее описание.

О чем поговорим:

  1. Кто я и почему решил пойти на стажировку?

  2. Контест

  3. Первое техническое интервью

  4. Второе техническое интервью

  5. Финальная встреча с куратором буткемпа

Кто я и почему решил пойти на стажировку?

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

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

Началась сероватая полоса
Началась сероватая полоса

Я захотел кардинально начать менять что-то в своей жизни. И вот как то раз мы собрались с друзьями в комнате почилить и довольно спонтанно решили поискать вакансии. Причем мы все загорелись этой идеей и буквально через несколько дней поиска, я нашел вакансию на позицию бекендера в Яндексе. В шутку, но решил все таки попытать удачу. На следующий день мне прислали письмо с приглашением пройти отбор. Как раз у рекрутера Полины я и узнал, о программе Deep Dive, которая предоставляла релокацию, что было для меня актуально. Заполнив анкетку я перешел к той части, ради которой вы сюда и зашли :)

Контест

После отправления заявки, мне пришла ссылка на Яндекс.Контест. За 6 часов нужно было решить 6 задач. Я выбрал время, чтобы никто и ничто меня не отвлекало, вооружился листочком с ручкой, чаечком с печеньками, открыл VS, включил музычку и тут понеслась.

Первые две задачки были не особо сложные, но на них я все-таки потратил какое-то время с волнения/непревычки. К третьей задаче у меня оставалась половина времени.
Третья задача была на знание контейнеров. Я сразу обратил внимание на ограничения в пару секунд и на огромные входные данные и понял, что тут за O(N) не пройти. И с этой задачей была настоящая схватка...

За час написано решение, но вот незадача, оно не проходит по времени! Посидел еще в коде какое то время, непонимающе, как можно еще ускорить алгоритм? Сложность должна подойти для ограничений!

Осталось около полутора часов. Я проглядел оставшиеся задачки и не понял вообще как их решать. Одна из них была связана работой с матрицей, вторая с работой с условиями про последнюю говорить страшно.
Оставался час и надо было добивать задачу. За примерно 40 минут я отловил бесконечный цикл (привет работа с итераторами) и исправил ситуацию, и о чудо! 4 тест пройден, упали на 5ом.
У меня 20 минут и 5тест из 60. Перечитать условие, посмотреть ограничения. Да! Обычный int не подходит, нужно использовать int64. За пару минут до решение проходит, однозначно победа.

Наконец-то достойный противник эта битва была легендарной!
Наконец-то достойный противник эта битва была легендарной!

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

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

Первое техническое интервью

Вот тут я начал по-настоящему напрягаться. Собеседование проходило по зуму и длилось ровно час. Я особо не готовился, хотел показать себя такой какой я есть. Друзья посоветовали положить на задний фон Мишку (так я назвал плюшевую игрушку - подушку, что мне подарили) для поддержки, как-нибудь не очень заметно. Все же серьезное собедование :)

Вот так выглядит Мишка
Вот так выглядит Мишка

Сперва мне дали задачку с СИ-строкой, что было для меня удивительно, я же вроде как на бекенд C++ подавал. Ну ладно СИ так си, все-таки алгоритмическое решение проверяют. Добрую половину часа я потратил. Поддерживало то, что интервьюер направлял на решение, подсказывая где могут возникнуть ошибки, а не осуждающе смотрел. Вообще мне понравилось как подсказывают интервьюеры - "вот представьте что у вас есть строка, ну небольшая такая на 5 гигабайт, как вы думаете, как быстро алгоритм ее обработает?". Сразу чувствуется, мыслят в реальных проектах более масштабно. Еще, если я предлагал какое-то неоптимальное решение у меня просили посчитать сложность своего алгоритма.

Разобравшись с первой задачкой мне задали достаточно озадачивающий вопрос. Он был связан с пониманием устройств контейнеров. Я понимаю, что при заканчивании свободного capacity у вектора с последующим push_back-ом, происходит релокация памяти с инвалидацией итераторов, а вставка в список происходит за O(1), но тем не менее вопрос меня удивил. Врочем включив логигу и некоторые знания я +-что-то ответил, не совсем правильно, не совсем то объяснение, которое ожидали от меня, но все равно это лучше чем промолчать.

Потом поспрашивали простенько про сортировку, тут особо то и нечего сказать.

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

В целом после собеседование у меня было слегка унылое настроение, ответив +- на половину. Но тем не менее я с надеждой ждал фидбека. И вот опять Полина обрадовала меня. Вскоре должно было состоятся второе интервью.

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

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

Первая задачка была опять на строки, но в этот раз уже на вход подается string, а не char* s. Вижу условие, на лице появляется улыбка, эту задачку я уже видел, когда готовился. Поискал свои листы, понял, что я просто ее проглядел, наклепав простенький алгоритм, не посмотрев достойного решения и принялся его описывать. Кстати да, в этот раз меня сначала попросили дать словесное описание алгоритма, а только потом его написать. Примерно набросав свою идею (она была не очень элегантной по коду, но вполне подошла по сложности), я принялся ее реализовывать.

мой муд в тот момент
мой муд в тот момент

Тут стоит обратить внимание на некоторые нюансы, которые возникли в ходе решения.

- А типа int для данной задачи нам хватит? А size_t? А если и этого мало, что бы я мог сделать?

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

И еще одна небольшая ошибка, о которой я понимал, но все же не приметил. Пусть s - объект типа string. В цикле я написал что-то типа

for (int i = 0; i < s.size(); i++)

Прошу находчивых отметить в комментариях, в чем тут ошибка :)

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

После интервью я опять немного напрягся, но в целом мне оно понравилось, мне дали пару советов на будущее, а беседа была позитивной. Вскоре последовал ответ от Полины. Меня пригласили на финальное собеседование с куратором буткемпа.

Финальная встреча с куратором буткемпа

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

Как всегда: зум,час, Мишка.

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

  1. Сперва мне рассказали о самом Яндекс.Маркете. Как развивается сервис, каковы его масштабы.

  2. Затем мне рассказали уже о проведении буткемпа. Период адаптации с тестовым заданием -> работа в первой команде -> работа во второй команде. И еще некоторые уточняющие детали.

  3. Вот это, пожалуй, самая интересная часть. Мне не давали вопросов по теории или каких-то задач, что меня приятно удивило. Но расспросили еще раз о интересных мне направлениях, о проектах, в которых я участвовал, работал ли в команде и какая была моя роль, что делал в случае возникновения ступора или когда понимал, что не успеваю выполнить задание. Некоторые из этих вопросов уже были в анкете, которую я подавал в самом начале, так что рекомендую про них вспомнить :)

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

Тут я чуть ли не подпрыгнул от радости, начал плясать, хлопать в ладоши, кричать на всю общагу "ура" и включил песню Survival из фильма Tomb Raider. Но тут мне учтивый сосед сообщил, что это еще не значит, что меня приняли на работу. Поэтому я ждал пока пройдут выходные, чтобы мне сообщили итоговый ответ. Вообщем после выходных мне снова написала Полина и уже окончательно сказала, что я принят. Мы созвонились, опять перешли на ты (тут я наконец-то к этому привык) и обговорили некоторые детали.

В заключение

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

В целом все собеседования проходили вполне комфортно, все интервьюеры вежливые и позитивные люди. Полине отдельный респект, за доброжеталельность :)

Желаю удачи всем будущим соискателям, не бойтесь пробовать и обращайтесь за "помощью" своих "Мишек" :)

Если к посту проявится интерес, то запилю ещё историю о прохождении стажировки и выживании в Москве.

Комментарии (25)


  1. KudryashovDA
    03.01.2022 17:59

    Поздравляю! Летом тоже пробовал попасть на стажировку, но второе собеседование завалил.
    По поводу

    for (int i = 0; i < s.size(); i++)

    Возможно придирка была к постфиксной записи инкремента. Давно когда-то встречал заметки на тему, что i++ дольше работает, чем ++i. Сейчас компиляторы вроде как сами оптимизируют эту конструкцию под капотом. Также может быть тема с int и size_t - что из-за разного типа может гипотетически произойти некорректное сравнение. Либо вообще хотели увидеть range based loop.


    1. tommyangelo27
      03.01.2022 18:41

      Я не пишу на C++ и не в курсе как именно размер строки хранится. Вопрос — s.size() будет вычисляться при каждой итерации или просто однократно берётся из структуры данных? Может быть имелось в виду, что нужно размер строки поместить во временную переменную?


      1. Ingulf
        04.01.2022 14:37

        size() имеет константную сложность для большинтсва контейнеров, скорее все же дело в int и size_t


      1. IgorPie
        06.01.2022 02:26

        Компиляторы сейчас очень умные. Вероятно, нужно было что-то типа s.length()


    1. horror_x
      03.01.2022 19:08
      +1

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

      Похожие чувства возникают, когда вижу как на современных версиях C продолжают писать как 30 лет назад. Принципиально объявляют переменные отдельно в начале функций, игнорируют существование const и т.п., хотя код всё равно не совместим с C89.


      1. Stronix
        03.01.2022 21:13
        +1

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

        https://en.cppreference.com/w/cpp/language/operator_incdec

        Pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.

        Post-increment and post-decrement creates a copy of the object, increments or decrements the value of the object and returns the copy from before the increment or decrement.

        Принципиально объявляют переменные отдельно в начале функций

        Иногда так удобнее высвобождать ресурсы.


        1. gecube
          03.01.2022 21:22
          +5

          В данном случае результат операции все равно выкидывается, так что цитата хорошая,и но толку от нее 0.


        1. horror_x
          03.01.2022 21:42

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


    1. gecube
      03.01.2022 19:34
      -2

      ТОЧНО НЕТ. Включайте логику.

      for (int i = 0; i < s.size(); i++)

      s.size() - это функция. Как думаете, если строчка мутирует ВНУТРИ цикла for - что мы получим? Я бы размер определял изначально, потом уже фигачил. Конечно, может быть супер оптимизирующий компилятор... но такое себе. Я уж не говорю о том, что такие штуки через итераторы пишут, потому что размер символа в байтах не определен точно...


      1. oleg-m1973
        03.01.2022 20:19
        +2

        Первое: int - это да, неправильно однозначно, там ещё и warning будет.

        Второе: Если длина строки изменяется внутри цикла, то нужно использовать именно i < s.size(), или типа того.


        1. gecube
          03.01.2022 20:33
          -1

          Если длина строки изменяется внутри цикла

          в этом случае можно получить любые приключения, включая неявный бесконечный цикл :-)


          1. oleg-m1973
            03.01.2022 20:40

            В том случае, с большой долей вероятности, получишь выход за границу массива


      1. Ingulf
        04.01.2022 14:48

        и так, вы определелили изначально размер строки, которая мутировала внутри цикла и стала меньге, если бы сравнение было с s.size(), цикл бы завершился и все было бы хорошо, а вот в вашем случае, мы продолжим индексироваться уже за пределами массива (строки), а это уже очень трагичное UB


    1. Kiel
      03.01.2022 21:13
      +3

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

      for(auto const& item :s)


    1. VitGo
      04.01.2022 06:35

      скорее разговор идет про s.size() если вспомнить про строки (обещанные аж в 5гб)... не знаю как в с++ но если при каждой итерации вычислять....

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

      (могу ошибаться)


      1. Ingulf
        04.01.2022 14:58

        опять же в чем проблема с вычислениями? какая ассимптокика у этого метода? в целом бля большинства контейнеров она константная


        1. Carburn
          04.01.2022 18:17

          Это лишнее время занимает в каждой итерации?


  1. gecube
    03.01.2022 18:03
    +7

    программирования все нет и нет, а есть одна иженерия)

    no comments. Будто программирование - не инженерия... Или хочется быть тупым кодером?


    1. psynix
      03.01.2022 18:05

      резковато конечно, но в целом верно )


    1. mag25 Автор
      04.01.2022 08:52
      +1

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


  1. valeramikhaylovsky
    03.01.2022 20:08

    На мой скромный взгляд цикл с подвохом, вместо него нужен range based for, тогда мы будем перемещаться от begin к end, а не заводить счётчики позиции.


  1. AirLight
    03.01.2022 23:53
    +1

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


  1. gurovofficial
    04.01.2022 07:47
    +1

    for (int i = 0; i < s.size(); i++)

    Самая серьёзная тут ошибка - это int. Там целая куча проблем всплывает:

    например, size_t(8) больше int(4) в два раза и что будет когда size_t перевалит int или

    например, i=-1 < s.size - тут i будет больше, если в size_t велечина в диапазоне int.

    Правильная запись:

    for (size_t i = 0; i < s.size(); ++i)

    Ещё лучше использовать итераторы или for(auto const& ch:s).


  1. mag25 Автор
    04.01.2022 08:38
    +2

    Благодарю модераторов и комментаторов за указание ошибок в тексте, писал по ночам в основном :)
    По поводу ошибки в цикле. Как многие заметили, дело было как раз в несоответствии типов. int и size_t.


  1. thebestvegetable
    05.01.2022 19:55

    Насчёт кода со строкой. Может быть потому что s.size() long unsigned int. Хотя не думаю что это большая проблема.int На 5 гб памяти хватит или нет не знаю