Это мой учебный план, рассчитанный на несколько месяцев для веб-разработчиков, не имеющих образования в Computer Science (CS)
и планирующих работать инженерами-программистами (software engineer) в компании Google.
За основу учебного плана я взял список вопросов Google's coaching notes и значительно расширил его. Тут вы найдёте
много полезных вещей, которые необходимо знать. Дополнительные вопросы я добавил в конец списка: их могут задавать на
интервью, a также они могут быть полезны в решении повседневных задач. Некоторые пункты я взял из поста Стива Йеги (Steve Yegge)
"Получить работу в Google", а некоторые слово в слово
соответствуют вопросам, разбираемых Google в их постах о подготовке.
Я сократил тот объем знаний, который необходим, по сравнению с рекомендациями Йеги. Я изменил требования Йеги исходя
из той информации, которую мне предоставил мой знакомый из Google. Это важно для тех, кто сейчас еще новички в
разработке программного обеспечения или являются веб-разработчиками и планируют стать инженерами-программистами
(это та профессия где требуются знания в области CS). Если вы опытный разработчик, ожидайте что собеседование будет сложным.
Подробнее.
Если вы обладаете многолетним опытом разработки ПО, помните, что Google разделяет понятия инженер-программист и
разработчик ПО/веб-разработчик. Первое требует знаний в области CS.
Если вы хотите быть инженерами обеспечивающими надежность ПО или системными инженерами, то уделите внимание вопросам из
опционального списка (разделы Сеть, Безопасность).
Я следую этому плану, готовясь к собеседованию в Google. Я разрабатываю веб-приложения, сервисы и запускаю стартапы с
1997 года. У меня есть степень по экономике, но нет по CS. На данный момент у меня очень успешная карьера, но я хочу работать
в Google. Я хочу работать с большими системами и понять принципы их работы, изучить эффективность алгоритмов и различные
структуры данных, узнать, как работают низкоуровневые языки программирования. Если ты не знаешь что-то из перечисленного,
Google не возьмёт тебя на работу.
Когда я начал этот проект, я ничего не знал о стеке, куче, Big-O, деревья и способах обхода графа. Если бы мне нужно
было писать код для сортировки, это было бы не очень хорошо. Структуры данных, которые я использовал, были частью языка,
и я не знал, как они на самом деле работали. Мне никогда не приходилось управлять памятью, если процесс, который я
запускал, сообщал об ошибке "out of memory", я искал способ как ее обойти. Я использовал в своей работе несколько
многомерных массивов и тысячи ассоциативных, но никогда не создавал структуру данных "с нуля".
Но после выполнения этого учебного плана я поверил, что Google меня наймет. Это длинный путь. Я потрачу на это месяцы.
Если вы уже знакомы с большинством тем, то потратите намного меньше времени.
Как пользоваться
Ниже описан способ использования, вы должны выполнить пункты в описанном порядке.
Я использую разметку Github, включающую список задач для оценки прогресса.
[x] Создай новую ветку и тогда ты сможешь оставлять отметки у элементов списка, просто добавляя x внутрь скобок: [x]
Скопируй репозиторий и выполни команды перечисленные ниже
Некоторые видео доступно в том случае, если вы являетесь слушателями курсов Coursera, EdX или Lynda.com
Их называют MOOCs. Некоторые курсы не имеют круглогодичного доступа и вам нужно подождать несколько месяцев,
прежде чем получите к ним доступ. Курсы на Lynda.com платные.
Я был бы вам благодарен за помощь в добавлении бесплатных, всегда доступных публичных ресурсов, таких
как видео с YouTube сопровождающих онлайн курсы. Мне нравится использовать университетские лекции.
Процесс собеседования & Основное в подготовке к интервью
На этапе собеседования, когда требуется программировать, вы можете использовать наиболее комфортный для вас язык
программирования. Для Google лучшим выбором будут следующие:
C++
Java
Python
Также подойдут:
JavaScript
Ruby
Вы должны хорошо знать выбранный язык и уметь комфортно писать на нём программы.
Книга была опубликована в 2004 и отчасти она устарела, но благодаря ей вы быстро поймете как устроены компьютеры.
Автор придумал HLA, поэтому скептически отнеситесь к примерам и упоминаниям HLA. Широко не используется, но содержит ряд примеров, демонстрирующих assembler.
Чтение следующих глав не займет много времени и даст хорошую основу:
Глава 2 - Представление в числовой форме
Глава 3 - Двоичная арифметика и битовые операции
Глава 4 - Представление числа с плавающей точкой
Глава 5 - Представление символа
Глава 6 - Организация памяти и доступа
Глава 7 - Составные типы данных и объекты в памяти
Глава 9 - Архитектура CPU
Глава 10 - Набор инструкций
Глава 11 - Архитектура и организация памяти
Если вы располагаете свободным временем (я хочу купить эту книгу):
Вам необходимо выбрать один язык для интервью (смотри выше). Здесь вы найдете мои рекомендации по языкам. У меня нет информации по всем языкам, но если есть у вас - добро пожаловать.
Если вы читали одну из них, то у вас есть достаточно знаний по алгоритмам и структурам данных и вы можете приступить к решению задач по программированию.
Вы можете пропустить все видео лекции в этом разделе, если не хотите повторить темы.
**Некоторые рекомендуют эти книги, но я думаю это перебор, если только вы не инженер-программист с большим опытом работы и не ожидаете более сложного собеседования.
автор описывает реальный опыт решения задач как академических, так и промышленных
примеры кода написаны на C
недостатки:
местами изложение может быть неочевидным и непонятным как в CLRS (Cormen, Leiserson, Rivest, Stein), некоторые темы лучше описаны в CLRS
главы 7, 8, 9 сложно понять, некоторые вещи плохо разъяснены или требуют больших знаний чем есть у меня
не поймите меня неправильно: Мне нравится Skiena, его стиль и манера изложения, но я не могу стать физически Stony Brook.
каталог алгоритмов:
это реальная причина, почему следует купить эту книгу.
о том, как дойти до этой части. Обновлю, когда изучу этот раздел.
Цитата Йеги: "Больше чем какая-либо другая книга, эта помогла мне понять насколько банальны задачи на графы - они должны
быть в инструментарии каждого программиста. Книга так же включает в себя разбор базовых структур данных и алгоритмов сортировки,
что является приятным бонусом. Но важнейшей частью стала вторая часть книги, которая написана как энциклопедия, описывающая большое
количество различных алгоритмических задач и способов их решения без лишних деталей. Почти каждая страница-описание содержит
изображение, облегчающее запоминание. Это полезный способ, позволяющий запомнить и в последствии идентифицировать сотни
типов задач."
Можете ее арендовать
Half.com - отличный ресурс, где можно заказать книги по выгодным ценам.
В первых двух главах представлены решения задач программирования (в некоторых из них используются устаревшие типы данных), но
это только введение. Это руководство по разработке программ и архитектуре, такое же как Code Complete, но более краткое.
"Алгоритмы и программирование: Проблемы и решения" автор Shen
Отличная книга, но после разбора нескольких задач написанных на Pascal я разочаровался в его синтаксисе.
Лучше провести время решая задачи по программированию из других книг или онлайн ресурсов.
Перед тем как вы начнете
Я создавал эту учебную программу на протяжении нескольких месяцев своими руками.
Ниже я описал некоторые ошибки, которые я совершил. Это поможет вам их избежать.
1. Вы не сможете сразу запомнить все
Я смотрел часами видео делая заметки, но спустя несколько месяцев многое из этого я не помнил. После чего потратил
3 дня разбираясь в своих заметках и делая карточки-напоминания (flashcards) для того, чтобы потом можно было повторить пройденный материал.
Прочитайте пожалуйста эту статью, что бы не совершать моих ошибок:
Моя база данных с карточками: Имейте в виду, я сделал больше чем требуется в Google, описав все начиная с assembler и заканчивая Python с машиным обучением и статистикой.
Заметка о карточках: в первый раз вы сразу вспомните ответ, но не помечайте эту карточку как изученную. Нужно просмотреть
много раз карточку и ответить правильно прежде чем вы действительно ее запомните. Повторение позволяет мозгу надолго
запомнить материал.
В качестве альтернативы вы можете использовать сайт Anki, который мне рекомендовали много раз. Он использует систему повторений для того что бы помочь вам запомнить.
Это ресурс user-friendly, доступен на всех платформах и имеет возможность синхронизации с облаком. На платформе iOS стоит 25$, на других бесплатный.
У меня постоянно с собой шпаргалки по ASCII, стеку OSI, Big-O нотации и другим темам. Я повторяю их когда у меня есть свободное время.
Делай перерывы от программирования на пол часа и повторяй свои карточки.
4. Фокусируйтесь
Есть много отвлекающих факторов, на которые тратится время. Сосредотачиваться и концентрироваться сложно.
То, что не охватывает этот учебный план
Это список персональных тем, взятых из заметок Google по подготовке к собеседованию. Это распространенные технологии,
но они не встречаются в других ресурсах:
SQL
JavaScript
HTML, CSS и другие front-end технологии
План на день
Для изучения некоторых тем требуется один день, для других несколько. Некоторые нужно только изучить и не нужно программировать.
Каждый день я беру одну тему из списка ниже, смотрю видео на эту тему и программирую, используя пройденный материал:
C - используя структуры и функции, которые в качестве аргументов принимают указатель на структуру или что-нибудь еще.
C++ - без использования встроенных типов
C++ - используя встроенные типы, такие как std::list для связанного списка
Python - используя встроенные типы (для практики на Python)
написание тестов для проверки правильности кода, иногда просто используя выражение assert()
Вы можете программировать на Java или других языках, это только лишь мой выбор.
Практика, практика, практика пока это не надоедает мне я программирую
Работа в рамках установленных ограничений (выделение/освобождение памяти без помощи сборщика мусора (кроме Python))
Используйте встроенные типы, потому как у меня есть опыт использования встроенных инструментах в реальных проектах (нет смысла в написание своей реализации связанного списка для продакшена)
У меня может и не будет времени на все это, но я попробую.
Это небольшая книга, но после ее прочтения вы получите необходимые знания по С и если будете практиковать,
то достаточно быстро его освоите. Понимание С поможет вам понять как работают программы и память.
Ага, попался: тебе нужны знания указателей на указатели:
(для тех случаев, когда ты передаешь указатель функции, которая может менять адрес, куда указывает указатель)
Это страница просто для того, чтобы понять указатели на указатели. Читабельность и обслуживаемость страдает
из-за искусности.
Реализация с использованием связанного списка и указателя на последний элемент(tail):
enqueue(value) - добавляет элемент в конец очереди
dequeue() - возвращает значение и удаляет из очереди последний добавленный элемент(front)
empty()
Реализация с применением массива фиксированного размера:
enqueue(value) - добавляет элемент в конец очереди
dequeue() - возвращает значение и удаляет из очереди последний добавленный элемент
empty()
full()
Затраты:
плохая реализация с применением связанного списка когда элемент добавляется в начало очереди и удаляется с конца очереди за O(n),
операция dequeue в таком случае будет требовать каждый раз обхода всего списка
enqueue: O(1) (amortized, связанный список и массив [probing])
get_max - возвращает максимальный элемент, не удаляя его
get_size() - возвращает количество хранящихся элементов
is_empty() - возвращает true если куча пустая
extract_max - возвращает максимальный элемент, удаляя его
sift_down - необходима для extract_max
remove(i) - удаляет элемент по индексу x
heapify - создает кучу из элементов массива, необходима для heap_sort
heap_sort() - берет не отсортированный массив и делает его отсортированным, не используя дополнительной памяти, кроме занимаемой самим массивом используя max heap
важно: можно использовать min heap, но тогда понадобиться доболнительная память.
Сортировка
[ ] Заметки:
Напиши код для разных сортировкок и помни про лучшую/худую, среднюю сложность для каждой:
не пузырьковая сортировка - она медленная - O(n^2), заисключением n <= 16
устойчивость в алгоритмах сортировки ("Быстрая сортировка устойчива?")
Я знаю, что классической книгой для изучения паттернов является "Приемы объектно-ориентированного проектирования. Паттерны проектирования" (Джон Влиссидес, Ральф Джонсон, Ричард Хелм, Эрих Гамма), но "Паттерны проектирования" отлично подходят для тех, кто только начал изучать ООП.
Здесь вы найдете статьи от Google, а также дургие известные статьи.
У вас вряд ли будет время прочитать их все с начала до конца. Я рекоммендую выбирать статьи и главы в них - тратье время грамотно на то, что хотите изучить глубже.
Проектирование систем, Масштабируемость, Обработка данных
Вы можете ожидать вопросов по проектированию систем если у вас 4+ лет опыта.
Масштабируемость и Проектирование систем это очень большие темы с большим количеством разделов и ресурсов, так как нужно многое учитывать при создании расширяемой программной/аппаратной системы. На освоение этого может уйти немало времени.
Заметки от Стива Йеги:
масштабируемость
Извленечние отдельных значений из больших наборов данных
Преобразование одних наборы данных в другие
Обработка неприлично больших объёмов данных
проектирование систем
наборы функций
интерфейсы
иерархии классов
проектирование системы удовлетворяющей определённым ограничениям
См. Ниже раздел «Системы обмена сообщениями, сериализации и управления очередями» для получения информации о некоторых технологиях, которые могут "склеивать" сервисы.
Чтобы узнать ещё больше, посмотрите серию видео "Mining Massive Datasets" в разделе "Серии видео".
Практика в проектировании систем: несколько идей чтобы проработать их с небольшим количеством информации о том, как это было сделано в действительности:
В этом разделе вы найдете короткие видео, которые можно посмотреть достаточно быстро чтобы повторить наиболее важные моменты.
Полезно освежать свои знания чаще.
Серия 2-3 минутных короткие видео по темам (23 видео)
Теперь, когда вы узнали все вышерассмотренные темы по компютерным наукам, настало время попрактиковаться в решении задач по программированию.
Решение задач по программированию - это не запоминание решений.
Для чего вам нужно практиковаться в решении задач по программированию:
выявление проблем, и умение определять какие структуры данных и алгоритмы походят для их решения
сбор требований для задачи
проговаривание хода решения задачи, так же как вы будете это делать на собеседовании
написание кода на доске или на бумаге, но не на компьютере
умение оценивать сложность вашего решения по расходу времени и памяти
тестирование решений
Вот пример отличного введения в методичное, коммуникативное решение задач на собеседовании. Вы так же найдете это в книгах по интервью для программистов, но это подход мне кажется однм из лучших:
Схема разработки алгоритма
У вас нет доски дома? Не удивительно. Я немного неормальный и у меня есть большая доска дома. Но вместо доски можно использователь и планшет для рисования из магазина художественных товаров, и практиковаться сидя на диване. Это моя "диванная доска". На фото я положил ручку чтобы иметь вы имели представление о масштабе. Если вы будете пользоваться ручкой, постоянно будет возникать желание что-то исправить и решение захламляется достаточно быстро.
Как только вы заполнили свою голову знаниями, самое время применить их на практике.
Выполняйте упражнения по программированию каждый день, чем больше тем лучше.
Загляните в раздел по подготовке резюме в книге Cracking The Coding Interview и в конце книги Programming Interviews Exposed
Подумайте об этом когда подходит время собеседования
Подумайте как отвечать приблизительно на 20 распостраненных вопросов которые задают на собеседовании, подготовьте 2-3 ответа на каждый из них.
Расскажите историю, а не просто сухой пересказ о том над чем вы работали.
Почему вы хотите получить эту работу?
Какая самая большая проблема которую вам приходилось решать?
Самые сложные задачи с которыми вам приходилось сталкиваться?
Лучшие/худшие дизайн решения с которыми вы сталкивались?
Идеи как улучшить какой-нибудь существующий продукт.
Вы более продуктивны как часть команды или как иднивидуальный разработчик?
Какие из ваших навыков или что из опыта будет наиболее ценным для данной позиции?
Что вам больше всего понравилось в работе над [проектом Х/в компании Х]?
Какие самые сложные задачи вы решали в [компании X/проекте Х]?
С каким самым сложным багом вам приходилось сталкиваться в [компании X/проекте Х]?
Чему вы научились в [компании X/проекте Х]?
Что бы вы могли сделать лучше работая в [компании X/проекте Х]?
Приготовьте вопросы для интервьювера
Вот, некоторые из моих (возможно, я уже знаю ответ, но хочу я услышать мнение интервьювера или точку зрения команды):
Сколько человек в команде?
Как выглядит ваш цикл разработки? Работаете ли вы по agile, спринтам или водопад?
Насколько часто бывают переработки и дедлайны? Или сроки достаточно гибкие?
Как в вашей команде принимаются решения?
Сколько встреч вы проводите в неделю?
Располагает ли ваше рабочее окружение к концентрации?
*****************************************************************************************************
*****************************************************************************************************
Все что находится ниже этого места - опционально. Это мои рекоммендации, а не от Google.
Изучая все это вы узнаете больше о компьютерных науках, и будуте лучше готовы для любой вакансии программиста.
Вы станете более всесторонне-развитым разработчиком.
*****************************************************************************************************
*****************************************************************************************************
Этот вопрос может быть довольно сложным, поскольку каждая разрешимая DP задача должна быть определена как рекурсивное отношение, и придумать его может быть сложно.
Я предлагаю рассмотреть много примеров проблем с DP, пока у вас не будет четкого понимания паттерна.
Видео:
the Skiena видео может быть не удобно смотреть, так как он иногда использует доску, которая слишком мала
Обратите внимание, что есть разные виды префиксных деревьев. Некоторые имеют префиксы, некоторые нет, а некоторые используют строку вместо битов
для отслеживания пути.
Знать как минимум один тип сбалансированного дерева поиска (и как его осуществить):
"Среди сбалансированных деревьев поиска AVL и 2/3 деревья теперь в прошлом, а красно-черные деревья все больше набирают популярность. Довольно интересный саморегулирующийся тип это расширяющееся дерево, который использует вращения для перемещения любого ключа к вершине" - Стивен Сол Лекена
Из всех них я предпочел написать расширяющееся дерево. Из того, что я читал, писать реализации сбалансированного дерева поиска во время интервью не понадобится. Но я хотел преодолеть еще одну задачу в програмировании, и будем честны, расширяющиеся деревья превосходны. Еще я прочитал довольно много про красно-черные деревья.
расширяющееся дерево: вставка, поиска, и удаление
Если вы решите реализовать красно-черное дерево напишите:
функции поиска и вставки, пропустите удаление
Я хочу изучить побольше про B-деревья, т.к. они применимы при работе с очень большими данными
In practice:
From what I can tell, these aren't used much in practice, but I could see where they would be:
The AVL tree is another structure supporting O(log n) search, insertion, and removal. It is more rigidly
balanced than red–black trees, leading to slower insertion and removal but faster retrieval. This makes it
attractive for data structures that may be built once and loaded without reconstruction, such as language
dictionaries (or program dictionaries, such as the opcodes of an assembler or interpreter).
In practice:
Splay trees are typically used in the implementation of caches, memory allocators, routers, garbage collectors,
data compression, ropes (replacement of string used for long text strings), in Windows NT (in the virtual memory,
networking and file system code) etc.
In practice:
Red–black trees offer worst-case guarantees for insertion time, deletion time, and search time.
Not only does this make them valuable in time-sensitive applications such as real-time applications,
but it makes them valuable building blocks in other data structures which provide worst-case guarantees;
for example, many data structures used in computational geometry can be based on red–black trees, and
the Completely Fair Scheduler used in current Linux kernels uses red–black trees. In the version 8 of Java,
the Collection HashMap has been modified such that instead of using a LinkedList to store identical elements with poor
hashcodes, a Red-Black tree is used.
На практике:
На каждое 2-4 дерево, существуют соответствующие красно-чёрные деревья с элементами данных в таком же порядке. Операции вставки и удаления на 2-4 деревьях эквивалентны изменению цвета и ротациям в красно-чёрных деревьях.
Таким образом, 2-4 деревья являются важным инструментом в понимании логики красно-чёрных деревьев, именно поэтому много вводных учебников по алгоритмам начинают с 2-4 деревьев прямо перед красно-черными, несмотря на то, что 2-4 деревья редко используются на практике.
забавно, но факт: это загадка, ведь B здесь может значить Boeing, сБалансированный, или Байер (фамилия ко-создателя)
На практике:
B-Деревья очень широко используются в базах данных. Большинство современных файловых систем используют B-деревья (или вариации, B+ и B* деревья).
В дополнение к использованию в базах данных, B-дерево также применяют в файловых системах для быстрого рандомного доступа к произвольному блоку в конкретном файле. Основная проблема это превратить адрес i файлового блока в адрес дискового блока или, например, в CHS (цилиндр-голова-сектор).
MIT 6.851 - Модели Иерархии Памяти (видео)
- включает кэш-агностические B-Деревья, крайне интересные структуры данных
- первые 37 минут очень технические, можно пропустить (B это размер блока, размер кэша)
I added these to reinforce some ideas already presented above, but didn't want to include them
above because it's just too much. It's easy to overdo it on a subject.
You want to get hired in this century, right?