Предупреждение: я не смогу привести в статье конкретные вопросы из-за подписанного соглашения о неразглашении (NDA).
Работая в лондонском офисе Facebook в команде Instagram*, я начал задумываться о возвращении в Индию. В ноябре 2022 года со мной связался рекрутер Google. Он сообщил об открытии в Бангалоре должности уровня L5 и спросил, интересно ли мне это.
Так как я уже раздумывал о переезде в Индию, то ранее собеседовался в Google, но мне предложили более низкую должность (L4), чем я хотел; потом я устроился в META* на уровень E5.
Я ответил рекрутеру, что хочу запланировать собеседование на март 2023 года, потому что готовился стать отцом и хотел в этот важный период выделить время для своей семьи.
Рекрутер согласился на мою просьбу и предоставил материалы для подготовки к собеседованию. Он сообщил, что свяжется со мной в марте. До этого момента он регулярно писал мне, чтобы узнать, как проходит моя подготовка.
На этот раз в процессе подготовки возникла уникальная для меня сложность — счастливое пополнение в моей семье, дочка. За моё внимание боролись подгузники и кодинг, было очень сложно выделить время на сосредоточенную подготовку! У меня было примерно 25-30 дней на освоение и искусства ухода за ребёнком, и прохождения собеседования.
Процесс подготовки
▍ Решено примерно 75 задач LeetCode
▍ Сделан упор на следующие темы для раунда по структурам данных и алгоритмам:
- Графы: BFS, DFS, топологическая сортировка, кратчайший путь.
- Деревья: двоичные деревья, деревья двоичного поиска, n-арные деревья.
- Префиксные деревья: префиксный поиск, поиск слов с подсчётом количества.
- Объединение непересекающихся множеств.
- Куча: медиана потока, максимум скользящего окна, верхние k элементов.
- Двоичный поиск: алгоритмы вычисления нижней и верхней границ, вопросы, в которых двоичный поиск не является очевидным выбором.
- Вопросы, связанные со скользящим окном и двумя указателями.
- Динамическое программирование.
- Строки: алгоритм Кнута — Морриса — Пратта, сортировка строк.
- Ситуативные вопросы о применении массивов, стеков, очередей, HashMap, TreeMap.
▍ Подготовка к собеседованию о проектировании систем:
- Прочитал несколько исследовательских статей:
Amazon Dynamo: Amazon’s Highly Available Key-Value Store
Spanner: Google’s Globally Distributed Database
Cassandra — A Decentralized Structured Storage System
- Попрактиковался в распространённых задачах проектирования систем, например, в проектировании сервиса сокращения URL, Pastebin, Instagram*, Dropbox, Facebook Messenger*, Twitter, YouTube/Netflix, рекомендаций по дальнейшему вводу (Typeahead Suggestion), ограничителя частоты доступа к API (API Rate Limiter), поиска в Twitter.
- Попрактиковался в проектировании систем для некоторых продуктов Google, в том числе для Google Поиска, YouTube, Google Photo Sharing и Storage, Google Документов, Google Диска.
- Повторил такие концепции проектирования систем, как теоремы CAP и PACELC, SQL и No-SQL, типы баз данных No-SQL и области их применения, согласованное хэширование (Consistent Hashing), Bloom-фильтры, балансировщики нагрузок (Load Balancer), горизонтальное масштабирование (Horizontal Scaling), кэширование, распределение/шардинг баз данных, индексы, ограничение скорости, распределённые очереди, дедупликация запросов.
- Посмотрел на YouTube несколько видео о проектировании систем.
▍ Прошёл семь имитаций собеседований — три с друзьями и четыре на Pramp
Мои собеседования
▍ Раунд 1 по структурам данных и алгоритмам (45 минут)
Деревья, обход в обратном порядке, топологическая сортировка
В процессе собеседования мне показали в редакторе кода длинный вопрос и попросили прочитать его. После прочтения я задал множество уточняющих вопросов, чтобы лучше понять задачу.
Получив чёткое представление, я предложил для решения использовать в качестве структуры данных дерево и применить обход в обратном порядке. Затем проводящий собеседование попросил, чтобы я объяснил решение на примере, что я и сделал.
После объяснения собеседующий попросил реализовать решение. Начав писать код, я намеревался сделать его модульным. Для этой цели я создал класс TreeNode, TreeClass и отдельный класс специально для решения задачи. Из-за временных ограничений и того, что я сделал упор на модульность, у меня возникли сложности, но в конечном итоге мне удалось написать работающий код.
У проводящего собеседование было несколько уточняющих вопросов, но он не смог задать их, потому что закончилось время. К концу раунда я понял, что провалил его. Позже я осознал, что ту же задачу можно было решить при помощи топологической сортировки.
▍ Раунд 2 по структурам данных и алгоритмам (1 час)
N-арные деревья, обход деревьев
Во втором раунде неожиданно оказалось, что на собеседование выделен 1 час, хотя обычно раунды по структурам данных и алгоритмам (DSA) в Google длятся 45 минут.
Сразу после начала собеседования я понял, почему длительность раунда увеличили. Проводящий собеседование показал мне задачу в документе Google, содержащем длинный вопрос, растянувшийся на 4-5 страниц. Кроме того, для исчерпывающего описания задачи там был слайд с диаграммой.
Увидев такую длинную задачу, я немного занервничал. Пока добрался до третьей страницы, я уже забыл подробности с предыдущих страниц. К счастью, собеседующий очень меня поддерживал и объяснил задачу. Я задал кучу уточняющих вопросов и мне понадобилось примерно 20-25 минут для полного понимания всех тонкостей задачи.
Длина решения задачи была под стать сложности вопроса. Задача была связана с деревьями, а именно с n-арными деревьями. Несмотря на сложности, мне удалось написать завершённый код. К концу раунда я чувствовал напряжение, но был уверен, что хорошо показал себя.
▍ Раунд 3 по структурам данных и алгоритмам (45 минут)
Задача с Leetcode среднего уровня, деревья, куча, рекурсия
Этот раунд отличался от двух предыдущих. Проводящий собеседование дал мне стандартную задачу с LeetCode среднего уровня, в которой делается упор на деревья. Я быстро предложил решение, доказал его работоспособность на примерах, а потом меня попросили написать код. Я быстро написал решение, указав его временную и пространственную сложность.
Дополнение 1: собеседующий немного изменил задачу и спросил, как бы я модифицировал код, чтобы он учитывал новую фичу. Я быстро придумал необходимое изменение, которое сделало мой код не только адаптируемым к модификации, но и более модульным для удобной адаптации к таким изменениям благодаря использованию шаблона проектирования «Стратегия».
Дополнение 2: собеседующий дал мне сложный уточняющий вопрос. Мне потребовалось некоторое время, чтобы найти оптимальное решение, ещё какое-то время потребовалось на объяснение решения на примерах. Внесённые ранее изменения по повышению модульности кода пошли на пользу, позволив мне быстро адаптироваться к изменениям, внесённым в дополнении 2. Мне удалось написать код вовремя.
Дополнение 3: оно было связано с превращением моего решения в продукт. Я рассказал о нескольких подходах, благодаря которым мой код мог бы работать в среде продакшена.
После завершения этого раунда я чувствовал себя уверенно.
Когда первые три раунда закончились, рекрутер сообщил, что в одном из раундов DSA мои результаты были спорными. Я уже догадывался об этом, потому что ощущал, что плохо проявил себя в раунде 1. Рекрутер порекомендовал провести дополнительный раунд DSA, чтобы у комиссии по найму не было сомнений, учитывая уверенные рекомендации о найме на основании двух других раундов.
▍ Раунд 4 по DSA (45 минут)
Строки, сортировка, двоичный поиск, префиксные деревья
В этом раунде мне пришлось понервничать. Проводящий собеседование изложил задачу, с которой я раньше не сталкивался. Хотя сама задача не была особо сложной, в ней требовалось применить множество концепций DSA: хэширование, сортировку, двоичный поиск, алгоритмы вычисления верхней и нижней границ, а также учесть пограничные случаи. Кроме того, собеседующий попросил написать качественные тесты.
Поразмыслив в течение примерно пяти минут (и проговаривая всё вслух), я смог выработать алгоритм для решения задачи. Я объяснил решение, подтвердил его на примерах, а затем указал временную и пространственную сложность решения. Затем проводящий собеседование попросил написать код. Я быстро написал код, создал тестовые сценарии и обеспечил покрытие всех пограничных случаев.
Дополнение 1: собеседующий задал уточняющий вопрос, внеся небольшое изменение во входные данные и ожидая ещё более оптимального решения. Рассмотрев несколько примеров, я придумал решение с использованием префиксных деревьев, что соответствовало ожиданиям собеседующего.
Дополнение 2: собеседующий задал мне вопросы о масштабируемости моего решения для обработки очень больших датасетов и его применимости в среде продакшена. Я порассуждал о возможности шардинга структуры данных префиксного дерева, перечислив различные стратегии эффективного шардинга. Кроме того, я описал альтернативное решение на основе хранилища пар «ключ-значение», однако мы не стали углубляться в его рассмотрение. После этого собеседующий попросил меня реализовать решение на основе префиксных деревьев.
Код для этого дополнения был довольно длинным, и мне пришлось торопиться, чтобы закончить его в срок. В целом, этот раунд прошёл хорошо.
▍ Раунд 5 по проектированию систем (45 минут)
Проводящий собеседование попросил меня спроектировать один из продуктов Google. Имея знания о системе, я перечислил функциональные и нефункциональные требования, обговорив их с собеседующим в нескольких уточняющих вопросах. Затем беседа перешла к подробному обсуждению конкретных фич, поэтому этот раунд оказался по своей сути более разговорным.
Мы подробно рассмотрели различные методики, тщательно рассмотрев плюсы и минусы каждой. Поддержка и взаимодействие со стороны собеседующего превратили этот раунд из типичного собеседования в обсуждение технических подробностей. В целом это был замечательный опыт.
С другой стороны, я не был уверен, насколько хорошо проявился в этом раунде.
▍ Раунд 6 по соответствию поведенческим требованиям Google (45 минут)
Мы подробно рассмотрели мой предыдущий опыт работы и причины решения уйти из META*. Затем собеседующий задал мне несколько вопросов на соответствие поведенческим требованиям компании (Googlyness), которые оказались ситуативными. Собеседующий представил множество интригующих сценариев, а я объяснял, как повёл бы себя в них, исходя из своих прошлых проектов и опыта. На протяжении всего процесса собеседующий был дружелюбным и поддерживающим.
В конечном итоге, этот раунд прошёл гладко, и после него у меня не было негативных ощущений.
Успешное прохождение собеседования в Google
Долгое время я с нетерпением ожидал результатов. Рекрутер сообщил, что они ожидают решения комиссии по найму. Спустя три недели рекрутер позвонил мне, чтобы поздравить: я прошёл собеседование в Google и комиссия по найму сказала, что результат положительный.
Переговоры об оффере и его принятие
В отличие от того времени, когда я получил оффер от META*, на этот раз особых переговоров об оффере не было. Первоначальный оффер соответствовал моим ожиданиям, поэтому я с радостью его принял.
Как и META*, Google предложил щедрое пособие по релокации, что сильно упростило переезд из Лондона в Бангалор.
Подбор команды
Процесс подбора команды в Google довольно долог. У меня было множество совещаний с менеджерами различных команд, чтобы найти подходящую мне. В конечном итоге я попал в команду Google Cloud Databases, которая показалась мне очень интересной.
Официально я устроился в Google 16 октября 2023 года. Вот краткая хроника:
- Ноябрь 2022 года: со мной связался рекрутер.
- Март 2023 года: я прошёл процесс собеседования
- Август 2023 года: получен оффер.
- Октябрь 2023 года: трудоустройство в Google.
▍ Основные выводы
- Развивайте в себе чёткое понимание структур данных и сфер их применений. В трёх раундах моего собеседования постоянно всплывала тема деревьев.
- Google делает упор на качество решения, в отличие от META*, где самое важное — это скорость его разработки.
- Ответы на уточняющие вопросы очень важны.
- Будьте готовы к длинным формулировкам задач и к написанию большого объёма кода на собеседовании.
- В некоторых уточняющих вопросах вам потребуется углубиться в сложности, связанные с реализацией вашего решения в среде продакшена.
Как и для большинства разработчиков ПО, трудоустройство в Google долгое время было моей мечтой. Google почитают за его культуру разработки, сложные задачи и инновационные технологии. Моей самой сильной мотивацией стала возможность работать в столь влиятельной компании вместе с одними из самых изобретательных умов в нашей отрасли.
После напряжённого процесса собеседования, потребовавшего тщательной подготовки, я с радостью могу теперь называть себя гуглером (Googler). Я жду непрерывного роста сложности при работе над важными проектами и расширения своих навыков, полученных при работе с талантливыми коллегами. Мне не терпится узнать, что будущее приготовило для этой новой главы в моей карьере.
Благодарю вас за прочтение статьи. Можете связаться со мной в LinkedIn, если нужна моя помощь! я с радостью помогу в подготовке к собеседованию или дам советы по развитию карьеры.
* Meta Platforms*, а также принадлежащие ей социальные сети Facebook** и Instagram**:
* — признана экстремистской организацией, её деятельность в России запрещена;
** — запрещены в России.
Автор:
ru_vds