Почему я не готовлюсь к алгоритмическому интервью

от автора

И не очень люблю людей, которые к нему «готовы». По моему мнению, главное на интервью — это понять как человек думает и как решает проблемы.

Если соискатель написал задачу за 5 минут правильно и оптимально, не переписывая в процессе несколько раз код, то… Никакой информации интервьюер не получит. Точнее придётся выбирать между версией, что на интервью бриллиант от программирования. И версией, что человек просто неплохо подготовился, а, возможно, вызубрил задачу наизусть.

Давайте проиллюстрирую на простенькой задаче.

В JS есть функции Math.round() — округление числа к ближайшему целому и Math.floor() — округление числа к меньшему целому. Нужно написать функцию (f) округления положительных чисел к ближайшему целому, используя только Math.floor. Чтобы чуть сократить путь — сразу ставим условие, что нам нужна функция стрелка в одну строку (без создания промежуточных переменных)

Есть очень простое и красивое решение, если соискатель его знает, то всё «плохо». Придётся доставать из загашника что-то ещё. А вдруг там пусто?

Но, пусть нам повезёт, и соискатель «не подготовился». Тогда, скажем, получим:

const f = (x) => x - Math.floor(x) >= 0.5 ? Math.floor(x) + 1 : Math.floor(x) 

Огонь! Соискатель знает что такое округление, понимает как получить дробную часть. Если не знает, я не против рассказать. Даже интереснее будет. Кстати, если нет скобок приоритета, как в данном выражении, и соискатель может объяснить почему, это огромный плюс. А если скобки есть, например, так:

const f = (x) => (x - Math.floor(x) < 0.5) ? Math.floor(x) : (Math.floor(x) + 1) 

То тут… нет криминала. Я сам, хоть не плаваю в вопросе приоритета операторов, но часто предпочитаю написать лишнюю скобку. И быть уверенным что все сработает так, как я задумал. Всё равно prettier лишние скобки корректно уберёт. А вот если чуть накосячить, то нужные он не поставит.

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

Пробуем повысить до миддла. Задаём вопрос: «А как сократить количество вызовов функции округления?»

const f = (x) => Math.floor(x) + (x - Math.floor(x) >= 0.5) ? 1 : 0  

Ок. Тут можно порассуждать: будет ли функция работать с отрицательными числами и почему нет. Ответил? Считаем, что миддл детектед. Опять же не точно, и нам бы, в идеале, нужен сеньор, хотя бы потенциальный. Поэтому усложняем : «А как сделать тоже самое, но с одним вызовом Math.floor?» И можно зависнуть в телефончик минуты на три (ибо вроде никак — нужна промежуточная переменная).

Выждав ровно 180 секунд, как и запланировано, выдаём подсказку: «И без тернарного оператора». Да-да, это подсказка. Даём ещё пару минут, но надеемся, что соискатель ещё не догадался. И предлагаем отложить задачу, а пока решить вот такую:

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

По прежнему нет идей? Хорошо, подсказка: «а что будет, если сложить 5 и 2?»

Не помогает, ладно, упрощаем задачу:

На вход приходит строго 0 или 1, нужно получить соответственно 1 и 0

const f = (x) => +!x 

Огонь. Кандидат умеет в идиомы и понимает в конверсии типов (в js префиксный плюс, это устоявшаяся идиома для конвертации в number, кстати, можно и про неё поговорить). Но нам нужно решить эту задачу со знаком минус, то есть с операцией вычитания, на что и намекаем. Если не помогает, что уже скорее грустно, подсказывает, что х надо именно отнять. Вопрос: от чего?
И, внезапно, сверкает лампочка:

const f = (x) => 1 - x  

Возвращаемся к задаче 5/2, уже проще? 5 + 2 = 7 значит:

const f = (x) => 7 - x 

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

Скрыл решение для тех, кто пока не догадался, но хочет таки сам
const f = (x) => Math.floor(x + 0.5) 

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

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

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

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

Поэтому на собеседовании не надо бояться, что задача идёт туго, нужно просто планомерно искать решение: умный интервьюер этого и добивается, а глупый… Ну что-то мне говорит, что не очень хорошая идея работать в коллективе, где все прошли через фильтр глупых интервьюеров. Если мне на собеседовании попадается задача, которую я знаю, я сразу говорю: «О! А я её на собесе яндекса решал: тут надо не постесняться сразу отсортировать массив, а дальше сложность только в …». Интервьюер может сразу перейти к запасному аэродрому, а может поговорить о задаче, попробовать усложнить условия, спросить ошибался ли я при решении и где.

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

И в реальном энтерпрайзе редко заморачиваешься, например, производительностью. Местами обосновано. Если у тебя n редко больше 10, а в среднем вообще n=1, то выбор между алгоритмами O(n log n) и в O(n3), только в том, какой легче написать, протестировать и поддерживать. Вот Microsoft со своей пузырьковой сортировкой иконок не даст соврать. Да плохой пример, но начальство любит больше того, кто за 15 минут выдаст код O(n2), чем того, кто неделю потратит на O(n log n), для списка выпадашек дропдауна. Есть области, в которых оптимизация чуть менее чем всего, необходима чуть реже чем всегда (например, игры), но 90% общего по миру кода, можно (и выгоднее) не оптимизировать. И да, это тоже часть работы, умение понимать, где надо, а где совсем нет.

И последнее (и закругляемся). Умение в алгоритмические задачи на пятерочку с плюсом, хорошо для джунов, и где-то миддлов. Видно, что человек заморачивается, прокачивает себя. И для сеньоров на позиции чистых RnD алгоритмистов — это их хлеб. А обычный сеньор, который оказывается звездой на leetcode вызывает вопросы. Когда он нашёл время на все эти задачки? И почему он хорошо помнит их решения (я вот несколько раз на собесах писал что-то по красно-черным деревьям, но дай мне задачу снова — снова буду тупить, решу, но буду тупить по ходу). У него много свободного было времени на прошлой работе? А работа? Дома? А не проще было что-то полезное пописать, не придумал свое — вон можно можно было в Линуксе до мантейнера дорасти.

Вывод: не надо бояться «сессии кодирования», там больше оценивают, что как вы думаете, а не что вы знаете. Плюс, предлагают вам интересные задачки, практически развлекают вас за их же деньги. Да «на встречу со звездой надо приходить подготовленными», но больше важно иметь представление о принципах и инструментах, чем об конкретных решениях.

Удачи на собесах. Обеим сторонам.

PS. По комментариям и не только (не спешите с гневными комментариями, возможно это сделали до вас)

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

Отдельная благодарность добровольным корректорам: @navferty, @redfox0, @sepetov, @Fedorkov.

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

О задаче. Нет, она не такая простая как кому-то кажется (в коментах люди тоже разделились на «это база» и «да ты охренел»). Да, это квиз, и её решение* должно давать кандидату плюс, а не решение* не должно давать минус. Нет, я её на реальных собеседования не даю в качеств основной. Пару раз давал, в ситуациях квантовой неопределенности с кандидатом. Оба кандидата и решивший и решивший не сразу — получили офферы и приняли их. Нет, никто из них не скандалил на собесе, получив эту задачу, как некоторые в коментах. А жаль, было бы весело.

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

В любом случае, спасибо за обратную связь.


ссылка на оригинал статьи https://habr.com/ru/articles/856904/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *