from: http://geek.csdn.net/news/detail/107064

  • 本文为掘金投稿,译文出自:掘金翻译计划
  • 原文地址:Google Interview University
  • 原文作者:John Washam
  • 译者:Aleen,Newton,bobmayuze,Jaeger,sqrthree
  • 友情提醒:文章较长,需耐心阅读。

这是?

这是我为了从 Web 开发者(自学、非计算机科学学位)蜕变至 Google 软件工程师所制定的计划,其内容历时数月。

这一长列表是从 Google 的指导笔记 中萃取出来并进行扩展。因此,有些事情你必须去了解一下。我在列表的底部添加了一些额外项,用于解决面试中可能会出现的问题。这些额外项大部分是来自于 Steve Yegge 的“得到在 Google 工作的机会”。而在 Google 指导笔记的逐字间,它们有时也会被反映出来。


目录

  • 这是?
  • 为何要用到它?
  • 如何使用它
  • 拥有一名 Googler 的心态
  • 我得到了工作吗?
  • 跟随着我
  • 不要自以为自己足够聪明
  • 关于 Google
  • 相关视频资源
  • 面试过程 & 通用的面试准备
  • 为你的面试选择一种语言
  • 在你开始之前
  • 你所看不到的
  • 日常计划
  • 必备知识
  • 算法复杂度 / Big-O / 渐进分析法
  • 数据结构
    • 数组(Arrays)
    • 链表(Linked Lists)
    • 堆栈(Stack)
    • 队列(Queue)
    • 哈希表(Hash table)
  • 更多的知识
    • 二分查找(Binary search)
    • 按位运算(Bitwise operations)
  • 树(Trees)
    • 树 —— 笔记 & 背景
    • 二叉查找树(Binary search trees):BSTs
    • 堆(Heap) / 优先级队列(Priority Queue) / 二叉堆(Binary Heap)
    • 字典树(Tries)
    • 平衡查找树(Balanced search trees)
    • N 叉树(K 叉树、M 叉树)
  • 排序
  • 图(Graphs)
  • 更多知识
    • 递归
    • 动态规划
    • 组合 & 概率
    • NP, NP-完全和近似算法
    • 缓存
    • 进程和线程
    • 系统设计、可伸缩性、数据处理
    • 论文
    • 测试
    • 调度
    • 实现系统例程
    • 字符串搜索和操作
  • 终面
  • 书籍
  • 编码练习和挑战
  • 当你临近面试时
  • 你的简历
  • 当面试来临的时候
  • 问面试官的问题
  • 当你获得了梦想的职位

—————- 下面的内容是可选的 —————-

  • 附加的学习

    • Unicode
    • 字节顺序
    • Emacs and vi(m)
    • Unix 命令行工具
    • 信息资源 (视频)
    • 奇偶校验位 & 汉明码 (视频)
    • 系统熵值(系统复杂度)
    • 密码学
    • 压缩
    • 网络 (视频)
    • 计算机安全
    • 释放缓存
    • 并行/并发编程
    • 设计模式
    • 信息传输, 序列化, 和队列化的系统
    • 快速傅里叶变换
    • 布隆过滤器
    • van Emde Boas 树
    • 更深入的数据结构
    • 跳表
    • 网络流
    • 不相交集 & 联合查找
    • 快速处理数学
    • 树堆 (Treap)
    • 线性规划
    • 几何:凸包(Geometry, Convex hull)
    • 离散数学
    • 机器学习
    • Go 语言
  • 一些主题的额外内容
  • 视频系列
  • 计算机科学课程

为何要用到它?

我一直都是遵循该计划去准备 Google 的面试。自 1997 年以来,我一直从事于 Web 程序的构建、服务器的构建及创业型公司的创办。对于只有着一个经济学学位,而不是计算机科学学位(CS degree)的我来说,在职业生涯中所取得的都非常成功。然而,我想在 Google 工作,并进入大型系统中,真正地去理解计算机系统、算法效率、数据结构性能、低级别编程语言及其工作原理。可一项都不了解的我,怎么会被 Google 所应聘呢?

当我创建该项目时,我从一个堆栈到一个堆都不了解。那时的我,完全不了解 Big-O 、树,或如何去遍历一个图。如果非要我去编写一个排序算法的话,我只能说我所写的肯定是很糟糕。一直以来,我所用的任何数据结构都是内建于编程语言当中。至于它们在背后是如何运作,对此我一概不清楚。此外,以前的我并不需要对内存进行管理,最多就只是在一个正在执行的进程抛出了“内存不足”的错误后,采取一些权变措施。而在我的编程生活中,也甚少使用到多维数组,可关联数组却成千上万。而且,从一开始到现在,我都还未曾自己实现过数据结构。

就是这样的我,在经过该学习计划后,已然对被 Google 所雇佣充满信心。这是一个漫长的计划,以至于花费了我数月的时间。若您早已熟悉大部分的知识,那么也许能节省大量的时间。

如何使用它

下面所有的东西都只是一个概述。因此,你需要由上而下逐一地去处理它。

在学习过程中,我是使用 GitHub 特殊的语法特性 markdown flavor 去检查计划的进展,包括使用任务列表。(注:因极客头条的 markdown 并不支持此语法,因此在下方做了删除处理)

更多关于 Github-flavored markdown 的详情

拥有一名 Googler 的心态

把一个(或两个)印有“future Googler”的图案打印出来,并用你誓要成功的眼神盯着它。

我得到了工作吗?

我还没去应聘。

因为我离完成学习(完成该疯狂的计划列表)还需要数天的时间,并打算在下周开始用一整天的时间,以编程的方式去解决问题。当然,这将会持续数周的时间。然后,我才通过使用在二月份所得到的一个介绍资格,去正式应聘 Google(没错,是二月份时就得到的)。

感谢 JP 的这次介绍。

跟随着我

目前我仍在该计划的执行过程中,如果你想跟随我脚步去学习的话,可以登进我在 GoogleyAsHeck.com 上所写的博客。

下面是我的联系方式:

  • Twitter: @googleyasheck
  • Twitter: @StartupNextDoor
  • Google+: +Googleyasheck
  • LinkedIn: johnawasham

不要自以为自己足够聪明

  • Google 的工程师都是才智过人的。但是,就算是工作在 Google 的他们,仍然会因为自己不够聪明而感到一种不安。
  • 天才程序员的神话

关于 Google

  • 面向学生 —— Google 的职业生涯:技术开发指导
  • Google 检索的原理:
    • Google 检索的发展史(视频)
    • Google 检索的原理 —— 故事篇
    • Google 检索的原理
    • Google 检索的原理 —— Matt Cutts(视频)
    • Google 是如何改善其检索算法(视频)
  • 系列文章:
    • Google 检索是如何处理移动设备
    • Google 为了寻找大众需求的秘密研究
    • Google 检索将成为你的下一个大脑
    • Demis Hassabis 的心灵直白
  • 书籍:Google 公司是如何运作的
  • 由 Google 通告所制作 —— 2016年10月(视频)

相关视频资源

部分视频只能通过在 Coursera、Edx 或 Lynda.com class 上注册登录才能观看。这些视频被称为网络公开课程(MOOC)。即便是免费观看,部分课程可能会由于不在时间段内而无法获取。因此,你需要多等待几个月。

很感谢您能帮我把网络公开课程的视频链接转换成公开的视频源,以代替那些在线课程的视频。此外,一些大学的讲座视频也是我所青睐的。

面试过程 & 通用的面试准备

  • 视频:

    • 如何在 Google 工作 —— 考生指导课程(视频)
    • Google 招聘者所分享的技术面试小窍门(视频)
    • 如何在 Google 工作:技术型简历的准备(视频)
  • 文章:

    • 三步成为 Googler
    • 得到在 Google 的工作机会
      • 所有他所提及的事情都列在了下面
    • (早已过期) 如何得到 Google 的一份工作,面试题,应聘过程
    • 手机设备屏幕的问题
  • 附加的(虽然 Google 不建议,但我还是添加在此):

    • ABC:永远都要去编程(Always Be Coding)
    • 四步成为 Google 里一名没有学位的员工
    • 共享白板(Whiteboarding)
    • Google 是如何看待应聘、管理和公司文化
    • 程序开发面试中有效的白板(Whiteboarding)
    • 震撼开发类面试 第一集:
      • Gayle L McDowell —— 震撼开发类面试(视频)
      • 震撼开发类面试 —— 作者 Gayle Laakmann McDowell(视频)
    • 如何在世界四强企业中获得一份工作:
      • “如何在世界四强企业中获得一份工作 —— Amazon、Facebook、Google 和 Microsoft”(视频)
    • 面试 Google 失败

为你的面试选择一种语言

在这,我就以下话题写一篇短文 —— 重点:为在 Google 的面试选择一种语言

在大多数公司的面试当中,你可以在编程这一环节,使用一种自己用起来较为舒适的语言去完成编程。但在 Google,你只有三种固定的选择:

  • C++
  • Java
  • Python

有时你也可以使用下面两种,但需要事先查阅说明。因为,说明中会有警告:

  • JavaScript
  • Ruby

你需要对你所选择的语言感到非常舒适且足够了解。

更多关于语言选择的阅读:

  • http://www.byte-by-byte.com/choose-the-right-language-for-your-coding-interview/
  • http://blog.codingforinterviews.com/best-programming-language-jobs/
  • https://www.quora.com/What-is-the-best-language-to-program-in-for-an-in-person-Google-interview

在此查看相关语言的资源

由于,我正在学习C、C++ 和 Python。因此,在下面你会看到部分关于它们的学习资料。相关书籍请看文章的底部。

在你开始之前

该列表已经持续更新了很长的一段时间,所以,我们的确很容易会对其失去控制。

这里列出了一些我所犯过的错误,希望您不要重滔覆辙。

1. 你不可能把所有的东西都记住

就算我查看了数小时的视频,并记录了大量的笔记。几个月后的我,仍然会忘却其中大部分的东西。所以,我翻阅了我的笔记,并将可回顾的东西制作成抽认卡(flashcard)(请往下看)

2. 使用抽认卡

为了解决善忘的问题,我制作了一些关于抽认卡的页面,用于添加两种抽认卡:正常的及带有代码的。每种卡都会有不同的格式设计。

而且,我还以移动设备为先去设计这些网页,以使得在任何地方的我,都能通过我的手机及平板去回顾知识。

你也可以免费制作属于你自己的抽认卡网站:

  • 抽认卡页面的代码仓库
  • 我的抽认卡数据库:有一点需要记住的是,我做事有点过头,以至于把卡片都覆盖到所有的东西上。从汇编语言和 Python 的细枝末节,乃至到机器学习和统计都被覆盖到卡片上。而这种做法,对于 Google 的要求来说,却是多余。

在抽认卡上做笔记: 若你第一次发现你知道问题的答案时,先不要急着把其标注成“已懂”。你需要做的,是去查看一下是否有同样的抽认卡,并在你真正懂得如何解决问题之前,多问自己几次。重复地问答可帮助您深刻记住该知识点。

3. 回顾,回顾,回顾

我留有一组 ASCII 码表、OSI 堆栈、Big-O 记号及更多的小抄纸,以便在空余的时候可以学习。

每编程半个小时就要休息一下,并去回顾你的抽认卡。

4. 专注

在学习的过程中,往往会有许多令人分心的事占据着我们宝贵的时间。因此,专注和集中注意力是非常困难的。

你所看不到的

由于,这个巨大的列表一开始是作为我个人从 Google 面试指导笔记所形成的一个事件处理列表。因此,有一些我熟悉且普遍的技术在此都未被谈及到:

  • SQL
  • Javascript
  • HTML、CSS 和其他前端技术

日常计划

部分问题可能会花费一天的时间去学习,而部分则会花费多天。当然,有些学习并不需要我们懂得如何实现。

因此,每一天我都会在下面所列出的列表中选择一项,并查看相关的视频。然后,使用以下的一种语言去实现:

C —— 使用结构体和函数,该函数会接受一个结构体指针 * 及其他数据作为参数。
C++ —— 不使用内建的数据类型。
C++ —— 使用内建的数据类型,如使用 STL 的 std::list 来作为链表。
Python ——  使用内建的数据类型(为了持续练习 Python),并编写一些测试去保证自己代码的正确性。有时,只需要使用断言函数 assert() 即可。
此外,你也可以使用 Java 或其他语言。以上只是我的个人偏好而已。

为何要在这些语言上分别实现一次?

因为可以练习,练习,练习,直至我厌倦它,并完美地实现出来。(若有部分边缘条件没想到时,我会用书写的形式记录下来并去记忆)
因为可以在纯原生的条件下工作(不需垃圾回收机制的帮助下,分配/释放内存(除了 Python))
因为可以利用上内建的数据类型,以使得我拥有在现实中使用内建工具的经验(在生产环境中,我不会去实现自己的链表)

就算我没有时间去每一项都这么做,但我也会尽我所能的。

在这里,你可以查看到我的代码:

  • C
  • C++
  • Python

你不需要记住每一个算法的内部原理。

在一个白板上写代码,而不要直接在计算机上编写。在测试完部分简单的输入后,到计算机上再测试一遍。

必备知识

  • 计算机是如何处理一段程序:

    • CPU 是如何执行代码(视频)
    • 机器码指令(视频)
  • 编译器

    • 编译器是如何在 ~1 分钟内工作(视频)
    • Hardvard CS50 —— 编译器(视频)
    • C++(视频)
    • 掌握编译器的优化(C++)(视频)
  • 浮点数是如何存储的:

    • 简单的 8-bit:浮点数的表达形式 —— 1(视频 —— 在计算上有一个错误 —— 详情请查看视频的介绍)
    • 32 bit:IEEE754 32-bit 浮点二进制(视频)

算法复杂度 / Big-O / 渐进分析法

  • 并不需要实现
  • Harvard CS50 —— 渐进表示(视频)
  • Big O 记号(通用快速教程)(视频)
  • Big O 记号(以及 Omega 和 Theta)—— 最佳数学解释(视频)
  • Skiena 算法:
    • 视频
    • 幻灯片
  • 对于算法复杂度分析的一次详细介绍
  • 增长阶数(Orders of Growth)(视频)
  • 渐进性(Asymptotics)(视频)
  • UC Berkeley Big O(视频)
  • UC Berkeley Big Omega(视频)
  • 平摊分析法(Amortized Analysis)(视频)
  • 举证“Big O”(视频)
  • 高级编程(包括递归关系和主定理):
    • 计算性复杂度:第一部
    • 计算性复杂度:第二部
  • 速查表(Cheat sheet)

    如果部分课程过于学术性,你可直接跳到文章底部,去查看离散数学的视频以获取相关背景知识。

数据结构

  • 数组(Arrays)

    • 实现一个可自动调整大小的动态数组。
    • 介绍:
      • 数组(视频)
      • 数组的基础知识(视频)
      • 多维数组(视频)
      • 动态数组(视频)
      • 不规则数组(视频)
      • 调整数组的大小(视频)
    • 实现一个动态数组(可自动调整大小的可变数组):
      • 练习使用数组和指针去编码,并且指针是通过计算去跳转而不是使用索引
      • 通过分配内存来新建一个原生数据型数组
        • 可以使用 int 类型的数组,但不能使用其语法特性
        • 从大小为16或更大的数(使用2的倍数 —— 16、32、64、128)开始编写
      • size() —— 数组元素的个数
      • capacity() —— 可容纳元素的个数
      • is_empty()
      • at(index) —— 返回对应索引的元素,且若索引越界则愤然报错
      • push(item)
      • insert(index, item) —— 在指定索引中插入元素,并把后面的元素依次后移
      • prepend(item) —— 可以使用上面的 insert 函数,传参 index 为 0
      • pop() —— 删除在数组末端的元素,并返回其值
      • delete(index) —— 删除指定索引的元素,并把后面的元素依次前移
      • remove(item) —— 删除指定值的元素,并返回其索引(即使有多个元素)
      • find(item) —— 寻找指定值的元素并返回其中第一个出现的元素其索引,若未找到则返回 -1
      • resize(new_capacity) // 私有函数
        • 若数组的大小到达其容积,则变大一倍
        • 获取元素后,若数组大小为其容积的1/4,则缩小一半
    • 时间复杂度
      • 在数组末端增加/删除、定位、更新元素,只允许占 O(1) 的时间复杂度(平摊(amortized)去分配内存以获取更多空间)
      • 在数组任何地方插入/移除元素,只允许 O(n) 的时间复杂度
    • 空间复杂度
      • 因为在内存中分配的空间邻近,所以有助于提高性能
      • 空间需求 = (大于或等于 n 的数组容积)* 元素的大小。即便空间需求为 2n,其空间复杂度仍然是 O(n)
  • 链表(Linked Lists)

    • 介绍:

      • 单向链表(视频)
      • CS 61B —— 链表(视频)
    • C 代码(视频)
      • 并非看完整个视频,只需要看关于节点结果和内存分配那一部分即可
    • 链表 vs 数组:
      • 基本链表 Vs 数组(视频)
      • 在现实中,链表 Vs 数组(视频)
    • 为什么你需要避免使用链表(视频)
    • 的确:你需要关于“指向指针的指针”的相关知识:(因为当你传递一个指针到一个函数时,该函数可能会改变指针所指向的地址)该页只是为了让你了解“指向指针的指针”这一概念。但我并不推荐这种链式遍历的风格。因为,这种风格的代码,其可读性和可维护性太低。
      • 指向指针的指针
    • 实现(我实现了使用尾指针以及没有使用尾指针这两种情况):
      • size() —— 返回链表中数据元素的个数
      • empty() —— 若链表为空则返回一个布尔值 true
      • value_at(index) —— 返回第 n 个元素的值(从0开始计算)
      • push_front(value) —— 添加元素到链表的首部
      • pop_front() —— 删除首部元素并返回其值
      • push_back(value) —— 添加元素到链表的尾部
      • pop_back() —— 删除尾部元素并返回其值
      • front() —— 返回首部元素的值
      • back() —— 返回尾部元素的值
      • insert(index, value) —— 插入值到指定的索引,并把当前索引的元素指向到新的元素
      • erase(index) —— 删除指定索引的节点
      • value_n_from_end(n) —— 返回倒数第 n 个节点的值
      • reverse() —— 逆序链表
      • remove_value(value) —— 删除链表中指定值的第一个元素
    • 双向链表
      • 介绍(视频)
      • 并不需要实现
  • 堆栈(Stack)

    • 堆栈(视频)
    • 使用堆栈 —— 后进先出(视频)
    • 可以不实现,因为使用数组来实现并不重要
  • 队列(Queue)

    • 使用队列 —— 先进先出(视频)
    • 队列(视频)
    • 原型队列/先进先出(FIFO)
    • 优先级队列(视频)
    • 使用含有尾部指针的链表来实现:
      • enqueue(value) —— 在尾部添加值
      • dequeue() —— 删除最早添加的元素并返回其值(首部元素)
      • empty()
    • 使用固定大小的数组实现:
      • enqueue(value) —— 在可容的情况下添加元素到尾部
      • dequeue() —— 删除最早添加的元素并返回其值
      • empty()
      • full()
    • 花销:
      • 在糟糕的实现情况下,使用链表所实现的队列,其入列和出列的时间复杂度将会是 O(n)。因为,你需要找到下一个元素,以致循环整个队列
      • enqueue:O(1)(平摊(amortized)、链表和数组 [探测(probing)])
      • dequeue:O(1)(链表和数组)
      • empty:O(1)(链表和数组)
  • 哈希表(Hash table)

    • 视频:

      • 链式哈希表(视频)
      • Table Doubling 和 Karp-Rabin(视频)
      • Open Addressing 和密码型哈希(Cryptographic Hashing)(视频)
      • PyCon 2010:The Mighty Dictionary(视频)
      • (进阶)随机取样(Randomization):全域哈希(Universal Hashing)& 完美哈希(Perfect Hashing)(视频)
      • (进阶)完美哈希(Perfect hashing)(视频)
    • 在线课程:

      • 哈希函数的掌握(视频)
      • 使用哈希表(视频)
      • 哈希表的支持(视频)
      • 哈希表的语言支持(视频)
      • 基本哈希表(视频)
      • 数据结构(视频)
      • 电话薄问题(Phone Book Problem)(视频)
      • 分布式哈希表:
        • Dropbox 中的瞬时上传及存储优化(视频)
        • 分布式哈希表(视频)
    • 使用线性探测的数组去实现

      • hash(k, m) —— m 是哈希表的大小
      • add(key, value) —— 如果 key 已存在则更新值
      • exists(key)
      • get(key)
      • remove(key)

更多的知识

  • 二分查找(Binary search)

    • 二分查找(视频)
    • 二分查找(视频)
    • 详情
    • 实现:
      • 二分查找(在一个已排序好的整型数组中查找)
      • 迭代式二分查找
  • 按位运算(Bitwise operations)

    • Bits 速查表

      • 你需要知道大量2的幂数值(从2^1 到 2^16 及 2^32)
    • 好好理解位操作符的含义:&、|、^、~、>>、<<
      • 字码(words)
      • 好的介绍:
        位操作(视频)
      • C 语言编程教程 2-10:按位运算(视频)
      • 位操作
      • 按位运算
      • Bithacks
      • 位元抚弄者(The Bit Twiddler)
      • 交互式位元抚弄者(The Bit Twiddler Interactive)
    • 一补数和补码
      • 二进制:利 & 弊(为什么我们要使用补码)(视频)
      • 一补数(1s Complement)
      • 补码(2s Complement)
    • 计算置位(Set Bits)
      • 计算一个字节中置位(Set Bits)的四种方式(视频)
      • 计算比特位
      • 如何在一个 32 位的整型中计算置位(Set Bits)的数量
    • 四舍五入2的幂数:
      • 四舍五入到2的下一幂数
    • 交换值:
      • 交换(Swap)
    • 绝对值:
      • 绝对整型(Absolute Integer)

树(Trees)

  • 树 —— 笔记 & 背景

    • 系列:基本树(视频)
    • 系列:树(视频)
    • 基本的树形结构
    • 遍历
    • 操作算法
    • BFS(广度优先检索,breadth-first search)
      • MIT(视频)
      • 层序遍历(使用队列的 BFS 算法)
        • 时间复杂度: O(n)
        • 空间复杂度:
          • 最好情况: O(1)
          • 最坏情况:O(n/2)=O(n)
    • DFS(深度优先检索,depth-first search)
      • MIT(视频)
      • 笔记:
        • 时间复杂度:O(n)
        • 空间复杂度:
          • 最好情况:O(log n) - 树的平均高度
          • 最坏情况:O(n)
      • 中序遍历(DFS:左、节点本身、右)
      • 后序遍历(DFS:左、右、节点本身)
      • 先序遍历(DFS:节点本身、左、右)
  • 二叉查找树(Binary search trees):BSTs

    • 二叉查找树概览(视频)
    • 系列(视频)
      • 从符号表开始到 BST 程序
    • 介绍(视频)
    • MIT(视频)
    • C/C++:
      • 二叉查找树 —— 在 C/C++ 中实现(视频)
      • BST 的实现 —— 在堆栈和堆中的内存分配(视频)
      • 在二叉查找树中找到最小和最大的元素(视频)
      • 寻找二叉树的高度(视频)
      • 二叉树的遍历 —— 广度优先和深度优先策略(视频)
      • 二叉树:层序遍历(视频)
      • 二叉树的遍历:先序、中序、后序(视频)
      • 判断一棵二叉树是否为二叉查找树(视频)
      • 从二叉查找树中删除一个节点(视频)
      • 二叉查找树中序遍历的后继者(视频)
    • 实现:
      • insert // 往树上插值
      • get_node_count // 查找树上的节点数
      • print_values // 从小到大打印树中节点的值
      • delete_tree
      • is_in_tree // 如果值存在于树中则返回 true
      • get_height // 返回节点所在的高度(如果只有一个节点,那么高度则为1)
      • get_min // 返回树上的最小值
      • get_max // 返回树上的最大值
      • is_binary_search_tree
      • delete_value
      • get_successor // 返回给定值的后继者,若没有则返回-1
  • 堆(Heap) / 优先级队列(Priority Queue) / 二叉堆(Binary Heap)

    • 可视化是一棵树,但通常是以线性的形式存储(数组、链表)
    • 介绍(视频)
    • 无知的实现(视频)
    • 二叉树(视频)
    • 关于树高的讨论(视频)
    • 基本操作(视频)
    • 完全二叉树(视频)
    • 伪代码(视频)
    • 堆排序 —— 跳到起点(视频)
    • 堆排序(视频)
    • 构建一个堆(视频)
    • MIT:堆与堆排序(视频)
    • CS 61B Lecture 24:优先级队列(视频)
    • 构建线性时间复杂度的堆(大顶堆)
    • 实现一个大顶堆:
      • insert
      • sift_up —— 用于插入元素
      • get_max —— 返回最大值但不移除元素
      • get_size() —— 返回存储的元素数量
      • is_empty() —— 若堆为空则返回 true
      • extract_max —— 返回最大值并移除
      • sift_down —— 用于获取最大值元素
      • remove(i) —— 删除指定索引的元素
      • heapify —— 构建堆,用于堆排序
      • heap_sort() —— 拿到一个未排序的数组,然后使用大顶堆进行就地排序
        • 注意:若用小顶堆可节省操作,但导致空间复杂度加倍。(无法做到就地)
  • 字典树(Tries)

    • 需要注意的是,字典树各式各样。有些有前缀,而有些则没有。有些使用字符串而不使用比特位来追踪路径。
    • 阅读代码,但不实现。
    • 数据结构笔记及编程技术
    • 短课程视频:
      • 对字典树的介绍(视频)
      • 字典树的性能(视频)
      • 实现一棵字典树(视频)
    • 字典树:一个被忽略的数据结构
    • 高级编程 —— 使用字典树
    • 标准教程(现实中的用例)(视频)
    • MIT,高阶数据结构,使用字符串追踪路径(可事半功倍)
  • 平衡查找树(Balanced search trees)

    • 掌握至少一种平衡查找树(并懂得如何实现):
    • “在各种平衡查找树当中,AVL 树和2-3树已经成为了过去,而红黑树(red-black trees)看似变得越来越受人青睐。这种令人特别感兴趣的数据结构,亦称伸展树(splay tree)。它可以自我管理,且会使用轮换来移除任何访问过根节点的 key。” —— Skiena
    • 因此,在各种各样的平衡查找树当中,我选择了伸展树来实现。虽然,通过我的阅读,我发现在 Google 的面试中并不会被要求实现一棵平衡查找树。但是,为了胜人一筹,我们还是应该看看如何去实现。在阅读了大量关于红黑树的代码后,我才发现伸展树的实现确实会使得各方面更为高效。
      • 伸展树:插入、查找、删除函数的实现,而如果你最终实现了红黑树,那么请尝试一下:
      • 跳过删除函数,直接实现搜索和插入功能
    • 我希望能阅读到更多关于 B 树的资料,因为它也被广泛地应用到大型的数据库当中。
    • 自平衡二叉查找树

    • AVL 树

      • 实际中:我能告诉你的是,该种树并无太多的用途,但我能看到有用的地方在哪里:AVL 树是另一种平衡查找树结构。其可支持时间复杂度为 O(log n) 的查询、插入及删除。它比红黑树严格意义上更为平衡,从而导致插入和删除更慢,但遍历却更快。正因如此,才彰显其结构的魅力。只需要构建一次,就可以在不重新构造的情况下读取,适合于实现诸如语言字典(或程序字典,如一个汇编程序或解释程序的操作码)。
      • MIT AVL 树 / AVL 树的排序(视频)
      • AVL 树(视频)
      • AVL 树的实现(视频)
      • 分离与合并
    • 伸展树

      • 实际中:伸展树一般用于缓存、内存分配者、路由器、垃圾回收者、数据压缩、ropes(字符串的一种替代品,用于存储长串的文本字符)、Windows NT(虚拟内存、网络及文件系统)等的实现。
      • CS 61B:伸展树(Splay trees)(视频)
      • MIT 教程:伸展树(Splay trees):
        • 该教程会过于学术,但请观看到最后的10分钟以确保掌握。
        • 视频
    • 2-3查找树

      • 实际中:2-3树的元素插入非常快速,但却有着查询慢的代价(因为相比较 AVL 树来说,其高度更高)。
      • 你会很少用到2-3树。这是因为,其实现过程中涉及到不同类型的节点。因此,人们更多地会选择红黑树。
      • 2-3树的直感与定义(视频)
      • 2-3树的二元观点
      • 2-3树(学生叙述)(视频)
    • 2-3-4树 (亦称2-4树)

      • 实际中:对于每一棵2-4树,都有着对应的红黑树来存储同样顺序的数据元素。在2-4树上进行插入及删除操作等同于在红黑树上进行颜色翻转及轮换。这使得2-4树成为一种用于掌握红黑树背后逻辑的重要工具。这就是为什么许多算法引导文章都会在介绍红黑树之前,先介绍2-4树,尽管2-4树在实际中并不经常使用
      • CS 61B Lecture 26:平衡查找树(视频)
      • 自底向上的2-4树(视频)
      • 自顶向下的2-4树(视频)
    • B 树

      • 有趣的是:为啥叫 B 仍然是一个神秘。因为 B 可代表波音(Boeing)、平衡(Balanced)或 Bayer(联合创造者)
      • 实际中:B 树会被广泛适用于数据库中,而现代大多数的文件系统都会使用到这种树(或变种)。除了运用在数据库中,B 树也会被用于文件系统以快速访问一个文件的任意块。但存在着一个基本的问题,那就是如何将文件块 i 转换成一个硬盘块(或一个柱面-磁头-扇区)上的地址。
      • B 树
      • B 树的介绍(视频)
      • B 树的定义及其插入操作(视频)
      • B 树的删除操作(视频)
      • MIT 6.851 —— 内存层次模块(Memory Hierarchy Models)(视频)
        • 覆盖有高速缓存参数无关型(cache-oblivious)B 树和非常有趣的数据结构
        • 头37分钟讲述的很专业,或许可以跳过(B 指块的大小、即缓存行的大小)
    • 红黑树

      • 实际中:红黑树提供了在最坏情况下插入操作、删除操作和查找操作的时间保证。这些时间值的保障不仅对时间敏感型应用有用,例如实时应用,还对在其他数据结构中块的构建非常有用,而这些数据结构都提供了最坏情况下的保障;例如,许多用于计算几何学的数据结构都可以基于红黑树,而目前 Linux 系统所采用的完全公平调度器(the Completely Fair Scheduler)也使用到了该种树。在 Java 8中,红黑树也被用于存储哈希列表集合中相同的数据,而不是使用链表及哈希码。
      • Aduni —— 算法 —— 课程4(该链接直接跳到开始部分)(视频)
      • Aduni —— 算法 —— 课程5(视频)
      • 黑树(Black Tree)
      • 二分查找及红黑树的介绍
  • N 叉树(K 叉树、M 叉树)

    • 注意:N 或 K 指的是分支系数(即树的最大分支数):

      • 二叉树是一种分支系数为2的树
      • 2-3树是一种分支系数为3的树
    • K 叉树

排序(Sorting)

  • 笔记:

    • 实现各种排序 & 知道每种排序的最坏、最好和平均的复杂度分别是什么场景:

      • 不要用冒泡排序 - 大多数情况下效率感人 - 时间复杂度 O(n^2), 除非 n <= 16
    • 排序算法的稳定性 (“快排是稳定的么?”)
      • 排序算法的稳定性
      • 排序算法的稳定性
      • 排序算法的稳定性
      • 排序算法的稳定性
      • 排序算法 - 稳定性
    • 哪种排序算法可以用链表?哪种用数组?哪种两者都可?
      • 并不推荐对一个链表排序,但归并排序是可行的.
      • 链表的归并排序
  • 关于堆排序,请查看前文堆的数据结构部分。堆排序很强大,不过是非稳定排序。

  • 冒泡排序 (video)

  • 冒泡排序分析 (video)
  • 插入排序 & 归并排序 (video)
  • 插入排序 (video)
  • 归并排序 (video)
  • 快排 (video)
  • 选择排序 (video)

  • 斯坦福大学关于排序算法的视频:

    • 课程 15 | 编程抽象 (video)
    • 课程 16 | 编程抽象 (video)
  • Shai Simonson 视频, Aduni.org:

    • 算法 - 排序 - 第二讲 (video)
    • 算法 - 排序2 - 第三讲 (video)
  • Steven Skiena 关于排序的视频:

    • 课程从 26:46 开始 (video)
    • 课程从 27:40 开始 (video)
    • 课程从 35:00 开始 (video)
    • 课程从 23:50 开始 (video)
  • 加州大学伯克利分校(UC Berkeley) 大学课程:

    • CS 61B 课程 29: 排序 I (video)
    • CS 61B 课程 30: 排序 II (video)
    • CS 61B 课程 32: 排序 III (video)
    • CS 61B 课程 33: 排序 V (video)
    • 归并排序:
    • 使用外部数组
    • 对原数组直接排序
    • 快速排序:
    • 实现
    • 实现
  • 实现:

    • 归并:平均和最差情况的时间复杂度为 O(n log n)。
    • 快排:平均时间复杂度为 O(n log n)。
    • 选择排序和插入排序的最坏、平均时间复杂度都是 O(n^2)。
    • 关于堆排序,请查看前文堆的数据结构部分。
  • 有兴趣的话,还有一些补充 - 但并不是必须的:

    • 基数排序
    • 基数排序 (video)
    • 基数排序, 计数排序 (线性时间内) (video)
    • 随机算法: 矩阵相乘, 快排, Freivalds’ 算法 (video)
    • 线性时间内的排序 (video)

图(Graphs)

图论能解决计算机科学里的很多问题,所以这一节会比较长,像树和排序的部分一样。

  • Yegge 的笔记:

    • 有 3 种基本方式在内存里表示一个图:

      • 对象和指针
      • 矩阵
      • 邻接表
    • 熟悉以上每一种图的表示法,并了解各自的优缺点
    • 宽度优先搜索和深度优先搜索 - 知道它们的计算复杂度和设计上的权衡以及如何用代码实现它们
    • 遇到一个问题时,首先尝试基于图的解决方案,如果没有再去尝试其他的。
  • Skiena 教授的课程 - 很不错的介绍:

    • CSE373 2012 - 课程 11 - 图的数据结构 (video)
    • CSE373 2012 - 课程 12 - 广度优先搜索 (video)
    • CSE373 2012 - 课程 13 - 图的算法 (video)
    • CSE373 2012 - 课程 14 - 图的算法 (1) (video)
    • CSE373 2012 - 课程 15 - 图的算法 (2) (video)
    • CSE373 2012 - 课程 16 - 图的算法 (3) (video)
  • 图 (复习和其他):

    • 6.006 单源最短路径问题 (video)
    • 6.006 Dijkstra 算法 (video)
    • 6.006 Bellman-Ford 算法(video)
    • 6.006 Dijkstra 效率优化 (video)
    • Aduni: 图的算法 I - 拓扑排序, 最小生成树, Prim 算法 - 第六课 (video)
    • Aduni: 图的算法 II - 深度优先搜索, 广度优先搜索, Kruskal 算法, 并查集数据结构 - 第七课 (video)
    • Aduni: 图的算法 III: 最短路径 - 第八课 (video)
    • Aduni: 图的算法. IV: 几何算法介绍 - 第九课 (video)
    • CS 61B 2014 (从 58:09 开始) (video)
    • CS 61B 2014: 加权图 (video)
    • 贪心算法: 最小生成树 (video)
    • 图的算法之强连通分量 Kosaraju 算法 (video)
  • 完整的 Coursera 课程:

    • 图的算法 (video)
  • Yegge: 如果有机会,可以试试研究更酷炫的算法:

    • Dijkstra 算法 - 上文 - 6.006
    • A* 算法
      • A* 算法
      • A* 寻路教程 (video)
      • A* 寻路 (E01: 算法解释) (video)
  • 我会实现:

    • DFS 邻接表 (递归)
    • DFS 邻接表 (栈迭代)
    • DFS 邻接矩阵 (递归)
    • DFS 邻接矩阵 (栈迭代)
    • BFS 邻接表
    • BFS 邻接矩阵
    • 单源最短路径问题 (Dijkstra)
    • 最小生成树
    • 基于 DFS 的算法 (根据上文 Aduni 的视频):
      • 检查环 (我们会先检查是否有环存在以便做拓扑排序)
      • 拓扑排序
      • 计算图中的连通分支
      • 列出强连通分量
      • 检查双向图

可以从 Skiena 的书(参考下面的书推荐小节)和面试书籍中学习更多关于图的实践。

更多知识

  • 递归(Recursion)

    • Stanford 大学关于递归 & 回溯的课程:

      • 课程 8 | 抽象编程 (video)
      • 课程 9 | 抽象编程 (video)
      • 课程 10 | 抽象编程 (video)
      • 课程 11 | 抽象编程 (video)
    • 什么时候适合使用
    • 尾递归会更好么?
      • 什么是尾递归以及为什么它如此糟糕?
      • 尾递归 (video)
  • 动态规划(Dynamic Programming)

    • This subject can be pretty difficult, as each DP soluble problem must be defined as a recursion relation, and coming up with it can be tricky.
    • 这一部分会有点困难,每个可以用动态规划解决的问题都必须先定义出递推关系,要推导出来可能会有点棘手。
    • 我建议先阅读和学习足够多的动态规划的例子,以便对解决 DP 问题的一般模式有个扎实的理解。

    • 视频:

      • Skiena 的视频可能会有点难跟上,有时候他用白板写的字会比较小,难看清楚。
      • Skiena: CSE373 2012 - 课程 19 - 动态规划介绍 (video)
      • Skiena: CSE373 2012 - 课程 20 - 编辑距离 (video)
      • Skiena: CSE373 2012 - 课程 21 - 动态规划举例 (video)
      • Skiena: CSE373 2012 - 课程 22 - 动态规划应用 (video)
      • Simonson: 动态规划 0 (starts at 59:18) (video)
      • Simonson: 动态规划 I - 课程 11 (video)
      • Simonson: 动态规划 II - 课程 12 (video)
      • 单独的 DP 问题 (每一个视频都很短):
        动态规划 (video)
    • Yale 课程笔记:
      • 动态规划
    • Coursera 课程:
      • RNA 二级结构问题 (video)
      • 动态规划算法 (video)
      • DP 算法描述 (video)
      • DP 算法的运行时间 (video)
      • DP vs 递归实现 (video)
      • 全局成对序列排列 (video)
      • 本地成对序列排列 (video)
  • 组合(Combinatorics) (n 中选 k 个) & 概率(Probability)

    • 数据技巧: 如何找出阶乘、排列和组合(选择) (video)
    • 来点学校的东西: 概率 (video)
    • 来点学校的东西: 概率和马尔可夫链 (video)
    • 可汗学院:
      • 课程设置:

        • 概率理论基础
      • 视频 - 41 (每一个都短小精悍):
        • 概率解释 (video)
  • NP, NP-完全和近似算法

    • 知道最经典的一些 NP 完全问题,比如旅行商问题和背包问题,
      而且能在面试官试图忽悠你的时候识别出他们。
    • 知道 NP 完全是什么意思.
    • 计算复杂度 (video)
    • Simonson:
      • 贪心算法. II & 介绍 NP-完全性 (video)
      • NP-完全性 II & 归约 (video)
      • NP-完全性 III (Video)
      • NP-完全性 IV (video)
    • Skiena:
      • [CSE373 2012 - 课程 23 - 介绍 NP-完全性 IV (video)](https://youtu.be/KiK5TVgXbFg?list=PLOtl7M3y

坚持完成这套学习手册,你就可以去 Google 面试了相关推荐

  1. (转) 坚持完成这套学习手册,你就可以去 Google 面试了

    坚持完成这套学习手册,你就可以去 Google 面试了 系统  指针  value  Google  面试 阅读6138  本文为掘金投稿,译文出自:掘金翻译计划 原文地址:Google Interv ...

  2. Google Interview University | 坚持完成这套学习手册,你就可以去 Google 面试了

    Google Interview University 一套完整的学习手册帮助自己准备 Google 的面试 原文地址:Google Interview University 原文作者:John Wa ...

  3. Google Interview University - 坚持完成这套学习手册,你就可以去 Google 面试了

    作者:Glowin 链接:https://zhuanlan.zhihu.com/p/22881223 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 原文地址:Goo ...

  4. GitHub 标星 8w!学完这份指南后,你就可以去 Google 面试了!

    点击上方"小詹学Python",选择"星标"公众号 重磅干货,第一时间送达 前言 如果让你选择一家互联网科技公司加入,你会选择哪一家? 具体答案因人而异,不过我 ...

  5. 直接拿来用!GitHub 标星 8W,学完它就可以去 Google 面试了!

    作者 | GitHubDaily 责编 | 郭芮 如果让你选择一家互联网科技公司加入,你会选择哪一家? 具体答案因人而异,不过我相信,作为目前全球最为知名的互联网公司,Google 一定名列其上. 自 ...

  6. [译] Google Interview University 一套完整的学习手册帮助自己准备 Google 的面试

    [译] Google Interview University 一套完整的学习手册帮助自己准备 Google 的面试 十一七天乐,看池博的github,发现这个markdown,转过来mark一下 原 ...

  7. 《ABAQUS 6.14超级学习手册》——1.2 ABAQUS分析模块

    本节书摘来自异步社区<ABAQUS 6.14超级学习手册>一书中的第1章,第1.2节,作者: 齐威 更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.2 ABA ...

  8. WhyGL:一套学习OpenGL的框架,及翻写Nehe的OpenGL教程

    最近在重学OpenGL,之所以说重学是因为上次接触OpenGL还是在学校里,工作之后就一直在搞D3D,一转眼已经毕业6年了.OpenGL这门手艺早就完全荒废了,现在只能是重学.学习程序最有效的办法是动 ...

  9. 编程入门到进大厂,你需要这套学习架构

    我相信大多数学习编程的同学都有着对大公司的憧憬.技术.声望.薪资.福利,这些都足以成为吸引你进入大厂的理由. 但是,如何进入大厂呢? 对于很多同学来说,通往大厂的道路并不明朗,不知道是否有希望,也不知 ...

最新文章

  1. Citrix通用打印服务器配置
  2. 福利 | 给你个机会与俞士纶(Philip S. Yu)面对面交流 !(附俞教授论文合集资源)...
  3. linux下使用yum安装新版php7.0
  4. go IDE 编译环境设置win32和win64
  5. openssl 生成证书_使用证书和私钥导出P12格式个人证书!
  6. 悲观锁 引起死锁_悲观锁定时如何避免可怕的死锁-以及Java 8的一些用法!
  7. 国家标准标点符号用法
  8. 理论篇-数理统计填坑篇
  9. 加载图片时报错,请大虾帮忙看看!
  10. 想要配置文件生效 需要通过添加到web.xml加载到内存中
  11. 教你手工去迅雷广告『罗斌原创』
  12. NSString 与 Unicode
  13. animation停留_animation控制动画暂停/播放
  14. Aho - Corasick string matching algorithm
  15. 高电平复位还是低电平复位?
  16. html chm 打不开,Win7系统中出现CHM打不开的具体解决方法
  17. 云函数能写php吗,FunctionCloud
  18. 8255A红绿灯c语言程序,汇编语言的交通灯程序
  19. TDMS如何用Excel打开编辑
  20. 【互联网人的英语】什么时候适合用“词根词缀法”来背单词?

热门文章

  1. Microsoft Visual Studio Learning Pack 自动生成流程图插件(转)
  2. 水晶报表——小代码,大作用(转自CSDN,阿泰)
  3. php 网址尾部带斜杠和不带区别,URL路径中带正斜杠/与不带的区别
  4. 蓝桥杯比赛常考算法_蓝桥杯总结-常用函数及算法
  5. Hibernate generator
  6. Golang闭包陷阱
  7. linux存储--文件描述符fd与FILE结构体(二)
  8. python list索引_Python按照索引访问list
  9. mysql c where_mysql where条件语句优化笔记
  10. 运用RUP 4+1视图方法进行软件架构设计