面试应该的准备
目录
- 日常计划
- 必备知识
- 算法复杂度 / Big-O / 渐进分析法
- 数据结构
- 更多的知识
- 树(Trees)
- 排序
- 图(Graphs)
- 更多知识
- 终面
- 书籍
- 编码练习和挑战
- 当你临近面试时
- 你的简历
- 当面试来临的时候
- 问面试官的问题
- 当你获得了梦想的职位
---------------- 下面的内容是可选的 ----------------
震撼开发类面试 第一集:
回顾,回顾,回顾
我留有一组 ASCII 码表、OSI 堆栈、Big-O 记号及更多的小抄纸,以便在空余的时候可以学习。
每编程半个小时就要休息一下,并去回顾你的抽认卡。
专注
在学习的过程中,往往会有许多令人分心的事占据着我们宝贵的时间。因此,专注和集中注意力是非常困难的。
在一个白板上写代码,而不要直接在计算机上编写。在测试完部分简单的输入后,到计算机上再测试一遍。
必备知识
算法复杂度 / Big-O / 渐进分析法
-
并不需要实现
-
如果部分课程过于学术性,你可直接跳到文章底部,去查看离散数学的视频以获取相关背景知识。
数据结构
-
数组(Arrays)
- 实现一个可自动调整大小的动态数组。
-
-
- 可以使用 int 类型的数组,但不能使用其语法特性
- 从大小为16或更大的数(使用2的倍数 —— 16、32、64、128)开始编写
-
- 若数组的大小到达其容积,则变大一倍
- 获取元素后,若数组大小为其容积的1/4,则缩小一半
-
-
- 在数组末端增加/删除、定位、更新元素,只允许占 O(1) 的时间复杂度(平摊(amortized)去分配内存以获取更多空间)
- 在数组任何地方插入/移除元素,只允许 O(n) 的时间复杂度
-
- 因为在内存中分配的空间邻近,所以有助于提高性能
- 空间需求 = (大于或等于 n 的数组容积)* 元素的大小。即便空间需求为 2n,其空间复杂度仍然是 O(n)
-
链表(Linked Lists)
-
-
- 并非看完整个视频,只需要看关于节点结果和内存分配那一部分即可
-
-
- 介绍(视频)
- 并不需要实现
-
-
堆栈(Stack)
-
队列(Queue)
-
- enqueue(value) —— 在尾部添加值
- dequeue() —— 删除最早添加的元素并返回其值(首部元素)
- empty()
-
- enqueue(value) —— 在可容的情况下添加元素到尾部
- dequeue() —— 删除最早添加的元素并返回其值
- empty()
- full()
-
- 在糟糕的实现情况下,使用链表所实现的队列,其入列和出列的时间复杂度将会是 O(n)。因为,你需要找到下一个元素,以致循环整个队列
- enqueue:O(1)(平摊(amortized)、链表和数组 [探测(probing)])
- dequeue:O(1)(链表和数组)
- empty:O(1)(链表和数组)
-
-
哈希表(Hash table)
-
-
- hash(k, m) —— m 是哈希表的大小
- add(key, value) —— 如果 key 已存在则更新值
- exists(key)
- get(key)
- remove(key)
-
更多的知识
-
二分查找(Binary search)
-
- 二分查找(在一个已排序好的整型数组中查找)
- 迭代式二分查找
-
-
按位运算(Bitwise operations)
树(Trees)
-
树 —— 笔记 & 背景
-
二叉查找树(Binary search trees):BSTs
-
- 从符号表开始到 BST 程序
- C/C++:
-
-
-
堆(Heap) / 优先级队列(Priority Queue) / 二叉堆(Binary Heap)
- 可视化是一棵树,但通常是以线性的形式存储(数组、链表)
-
-
- 注意:若用小顶堆可节省操作,但导致空间复杂度加倍。(无法做到就地)
-
-
字典树(Tries)
- 需要注意的是,字典树各式各样。有些有前缀,而有些则没有。有些使用字符串而不使用比特位来追踪路径。
- 阅读代码,但不实现。
-
-
平衡查找树(Balanced search trees)
-
掌握至少一种平衡查找树(并懂得如何实现):
-
“在各种平衡查找树当中,AVL 树和2-3树已经成为了过去,而红黑树(red-black trees)看似变得越来越受人青睐。这种令人特别感兴趣的数据结构,亦称伸展树(splay tree)。它可以自我管理,且会使用轮换来移除任何访问过根节点的 key。” —— Skiena
-
因此,在各种各样的平衡查找树当中,我选择了伸展树来实现。虽然,通过我的阅读,我发现在 Google 的面试中并不会被要求实现一棵平衡查找树。但是,为了胜人一筹,我们还是应该看看如何去实现。在阅读了大量关于红黑树的代码后,我才发现伸展树的实现确实会使得各方面更为高效。
- 伸展树:插入、查找、删除函数的实现,而如果你最终实现了红黑树,那么请尝试一下:
- 跳过删除函数,直接实现搜索和插入功能
-
我希望能阅读到更多关于 B 树的资料,因为它也被广泛地应用到大型的数据库当中。
-
- 实际中:我能告诉你的是,该种树并无太多的用途,但我能看到有用的地方在哪里:AVL 树是另一种平衡查找树结构。其可支持时间复杂度为 O(log n) 的查询、插入及删除。它比红黑树严格意义上更为平衡,从而导致插入和删除更慢,但遍历却更快。正因如此,才彰显其结构的魅力。只需要构建一次,就可以在不重新构造的情况下读取,适合于实现诸如语言字典(或程序字典,如一个汇编程序或解释程序的操作码)。
-
- 实际中:伸展树一般用于缓存、内存分配者、路由器、垃圾回收者、数据压缩、ropes(字符串的一种替代品,用于存储长串的文本字符)、Windows NT(虚拟内存、网络及文件系统)等的实现。
-
- 该教程会过于学术,但请观看到最后的10分钟以确保掌握。
- 视频
-
- 实际中:2-3树的元素插入非常快速,但却有着查询慢的代价(因为相比较 AVL 树来说,其高度更高)。
- 你会很少用到2-3树。这是因为,其实现过程中涉及到不同类型的节点。因此,人们更多地会选择红黑树。
-
- 实际中:对于每一棵2-4树,都有着对应的红黑树来存储同样顺序的数据元素。在2-4树上进行插入及删除操作等同于在红黑树上进行颜色翻转及轮换。这使得2-4树成为一种用于掌握红黑树背后逻辑的重要工具。这就是为什么许多算法引导文章都会在介绍红黑树之前,先介绍2-4树,尽管2-4树在实际中并不经常使用。
-
- 有趣的是:为啥叫 B 仍然是一个神秘。因为 B 可代表波音(Boeing)、平衡(Balanced)或 Bayer(联合创造者)
- 实际中:B 树会被广泛适用于数据库中,而现代大多数的文件系统都会使用到这种树(或变种)。除了运用在数据库中,B 树也会被用于文件系统以快速访问一个文件的任意块。但存在着一个基本的问题,那就是如何将文件块 i 转换成一个硬盘块(或一个柱面-磁头-扇区)上的地址。
-
- 覆盖有高速缓存参数无关型(cache-oblivious)B 树和非常有趣的数据结构
- 头37分钟讲述的很专业,或许可以跳过(B 指块的大小、即缓存行的大小)
-
- 实际中:红黑树提供了在最坏情况下插入操作、删除操作和查找操作的时间保证。这些时间值的保障不仅对时间敏感型应用有用,例如实时应用,还对在其他数据结构中块的构建非常有用,而这些数据结构都提供了最坏情况下的保障;例如,许多用于计算几何学的数据结构都可以基于红黑树,而目前 Linux 系统所采用的完全公平调度器(the Completely Fair Scheduler)也使用到了该种树。在 Java 8中,红黑树也被用于存储哈希列表集合中相同的数据,而不是使用链表及哈希码。
-
-
N 叉树(K 叉树、M 叉树)
- 注意:N 或 K 指的是分支系数(即树的最大分支数):
- 二叉树是一种分支系数为2的树
- 2-3树是一种分支系数为3的树
- 注意:N 或 K 指的是分支系数(即树的最大分支数):
排序(Sorting)
-
关于堆排序,请查看前文堆的数据结构部分。堆排序很强大,不过是非稳定排序。
-
-
-
-
-
-
-
- 选择排序和插入排序的最坏、平均时间复杂度都是 O(n^2)。
- 关于堆排序,请查看前文堆的数据结构部分。
-
图(Graphs)
图论能解决计算机科学里的很多问题,所以这一节会比较长,像树和排序的部分一样。
-
Yegge 的笔记:
- 有 3 种基本方式在内存里表示一个图:
- 对象和指针
- 矩阵
- 邻接表
- 熟悉以上每一种图的表示法,并了解各自的优缺点
- 宽度优先搜索和深度优先搜索 - 知道它们的计算复杂度和设计上的权衡以及如何用代码实现它们
- 遇到一个问题时,首先尝试基于图的解决方案,如果没有再去尝试其他的。
- 有 3 种基本方式在内存里表示一个图:
-
-
-
完整的 Coursera 课程:
-
Yegge: 如果有机会,可以试试研究更酷炫的算法:
-
-
我会实现:
- 基于 DFS 的算法 (根据上文 Aduni 的视频):
- 基于 DFS 的算法 (根据上文 Aduni 的视频):
可以从 Skiena 的书(参考下面的书推荐小节)和面试书籍中学习更多关于图的实践。
更多知识
-
递归(Recursion)
-
- 什么时候适合使用
- 尾递归会更好么?
-
-
动态规划(Dynamic Programming)
-
注意 :动态规划是门极为重要的技术,尽管其并未被 Google 提供的准备手册提及,但你可能会对寻求最佳解的方式有点疑问,所以我将其列入这份表单。
-
这一部分会有点困难,每个可以用动态规划解决的问题都必须先定义出递推关系,要推导出来可能会有点棘手。
-
我建议先阅读和学习足够多的动态规划的例子,以便对解决 DP 问题的一般模式有个扎实的理解。
-
- Skiena 的视频可能会有点难跟上,有时候他用白板写的字会比较小,难看清楚。
-
-
-
-
组合(Combinatorics) (n 中选 k 个) & 概率(Probability)
-
- 课程设置:
- 视频 - 41 (每一个都短小精悍):
- 课程设置:
-
-
NP, NP-完全和近似算法
- 知道最经典的一些 NP 完全问题,比如旅行商问题和背包问题,
而且能在面试官试图忽悠你的时候识别出他们。 - 知道 NP 完全是什么意思.
-
-
- Peter Norvik 讨论旅行商问题的近似最优解:
- 《算法导论》的第 1048 - 1140 页。
- 知道最经典的一些 NP 完全问题,比如旅行商问题和背包问题,
-
缓存(Cache)
-
-
进程(Processe)和线程(Thread)
-
- 视频 1-11 是关于进程和线程
- 操作系统和系统编程 (video)
- 进程和线程的区别是什么?
- 涵盖了:
- 进程、线程、协程
- 进程和线程的区别
- 进程
- 线程
- 锁
- 互斥
- 信号量
- 监控
- 他们是如何工作的
- 死锁
- 活锁
- CPU 活动, 中断, 上下文切换
- 现代多核处理器的并发式结构
- 进程资源需要(内存:代码、静态存储器、栈、堆、文件描述符、I/O)
- 线程资源需要(在同一个进程内和其他线程共享以上的资源,但是每个线程都有独立的程序计数器、栈计数器、寄存器和栈)
- Fork 操作是真正的写时复制(只读),直到新的进程写到内存中,才会生成一份新的拷贝。
- 上下文切换
- 操作系统和底层硬件是如何初始化上下文切换的。
- 进程、线程、协程
系统设计以及可伸缩性,要把软硬件的伸缩性设计的足够好有很多的东西要考虑,所以这是个包含非常多内容和资源的大主题。需要花费相当多的时间在这个主题上。
-
-
系统设计、可伸缩性、数据处理
- Yegge 的注意事项:
- 伸缩性
- 把大数据集提取为单一值
- 大数据集转换
- 处理大量的数据集
- 系统
- 特征集
- 接口
- 类层次结构
- 在特定的约束下设计系统
- 轻量和健壮性
- 权衡和折衷
- 性能分析和优化
- 伸缩性
-
- 如果你对 OO 都深刻的理解和实践,可以跳过这部分。
- OOSE: 使用 UML 和 Java 开发软件
-
- 更多内容可以查看视频部分的『大规模数据挖掘』视频系列。
-
- 复习: HiredInTech 的系统设计
- cheat sheet
- 流程:
- 理解问题和范围:
- 在面试官的帮助下定义用例
- 提出附加功能的建议
- 去掉面试官认定范围以外的内容
- 假定高可用是必须的,而且要作为一个用例
- 考虑约束:
- 问一下每月请求量
- 问一下每秒请求量 (他们可能会主动提到或者让你算一下)
- 评估读写所占的百分比
- 评估的时候牢记 2/8 原则
- 每秒写多少数据
- 总的数据存储量要考虑超过 5 年的情况
- 每秒读多少数据
- 抽象设计:
- 分层 (服务, 数据, 缓存)
- 基础设施: 负载均衡, 消息
- 粗略的概括任何驱动整个服务的关键算法
- 考虑瓶颈并指出解决方案
- 理解问题和范围:
- 练习:
- Yegge 的注意事项:
-
论文
-
测试
- 涵盖了:
- 单元测试是如何工作的
- 什么是模拟对象
- 什么是集成测试
- 什么是依赖注入
-
- 涵盖了:
-
调度
- 在操作系统中是如何运作的
- 在操作系统部分的视频里有很多资料
-
实现系统例程
- 理解你使用的系统 API 底层有什么
- 你能自己实现它们么?
-
字符串搜索和操作
终面
这一部分有一些短视频,你可以快速的观看和复习大多数重要概念。
这对经常性的巩固很有帮助。
综述:
排序:
书籍
Google Coaching 里提到的
阅读并做练习:
-
- 书 (Kindle 上可以租到):
- Half.com 是一个资源丰富且性价比很高的在线书店.
- 答案:
- 勘误表
read and do exercises from the books below. Then move to coding challenges (further down below)
一旦你理解了每日计划里的所有内容,就去读上面所列的书并完成练习,然后开始读下面所列的书并做练习,之后就可以开始实战写代码了(本文再往后的部分)
首先阅读:
然后阅读 (这本获得了很多推荐, 但是不在 Google coaching 的文档里):
-
- 如果你看到有人在看 "The Google Resume", 实际上它和 "Cracking the Coding Interview" 是同一个作者写的,而且后者是升级版。
附加书单
这些没有被 Google 推荐阅读,不过我因为需要这些背景知识所以也把它们列在了这里。
如果你有时间
-
- 如果你希望在面试里用 C++ 写代码,这本书的代码全都是 C++ 写的
- 通常情况下能找到解决方案的好书.
编码练习和挑战
一旦你学会了理论基础,就应该把它们拿出来练练。
尽量坚持每天做编码练习,越多越好。
编程问题预备:
编码练习平台:
当你临近面试时
你的简历
- 10 条小贴士让你写出一份还算不错的简历
- 这是搞定面试的第一个关键步骤
当面试来临的时候
随着下面列举的问题思考下你可能会遇到的 20 个面试问题
每个问题准备 2-3 种回答
准备点故事,不要只是摆一些你完成的事情的数据,相信我,人人都喜欢听故事
- 你为什么想得到这份工作?
- 你解决过的最有难度的问题是什么?
- 面对过的最大挑战是什么?
- 见过的最好或者最坏的设计是怎么样的?
- 对某项 Google 产品提出改进建议。
- 你作为一个个体同时也是团队的一员,如何达到最好的工作状态?
- 你的什么技能或者经验是你的角色中不可或缺的?为什么?
- 你在某份工作或某个项目中最享受的是什么?
- 你在某份工作或某个项目中面临过的最大挑战是什么?
- 你在某份工作或某个项目中遇到过的最蛋疼的 Bug 是什么样的?
- 你在某份工作或某个项目中学到了什么?
- 你在某份工作或某个项目中哪些地方还可以做的更好?
问面试官的问题
我会问的一些:(可能我已经知道了答案但我想听听面试官的看法或者了解团队的前景):
- 团队多大规模?
- 开发周期是怎样的? 会使用瀑布流/极限编程/敏捷开发么?
- 经常会为 deadline 加班么? 或者是有弹性的?
- 团队里怎么做技术选型?
- 每周平均开多少次会?
- 你觉得工作环境有助于员工集中精力吗?
- 目前正在做什么工作?
- 喜欢这些事情吗?
- 工作期限是怎么样的?
当你获得了梦想的职位
我还能说些什么呢,恭喜你!
坚持继续学习。
得到这份工作只是一个开始。
*****************************************************************************************************
*****************************************************************************************************
下面的内容都是可选的。这些是我的推荐,不是 Google 的。
通过学习这些内容,你将会得到更多的有关 CS 的概念,并将为所有的软件工程工作做更好的准备。
*****************************************************************************************************
*****************************************************************************************************
附加的学习
-
Unicode
-
字节顺序
-
- 内核开发者的讨论非常技术性,如果大多数都超出了你的理解范围,不要太担心。
- 前半段已经足够了。
-
-
Emacs and vi(m)
- Yegge 的建议,从一个很早以前的亚马逊招聘信息中而来:熟悉基于 unix 的代码编辑器
- vi(m):
- emacs:
-
Unix 命令行工具
- 下列内容中的优秀工具由的 Yegge 推荐,Yegge 目前致力于 Amazon 人事招聘处。
-
信息资源 (视频)
-
- 关于更多信息,请参照下方 MIT 6.050J 信息和系统复杂度的内容.
-
-
奇偶校验位 & 汉明码 (视频)
-
系统熵值(系统复杂度)
- 请参考下方视频
- 观看之前,请先确定观看了信息论的视频
-
密码学
- 请参考下方视频
- 观看之前,请先确定观看了信息论的视频
-
压缩
- 观看之前,请先确定观看了信息论的视频
-
-
网络 (视频)
-
计算机安全
-
释放缓存
-
并行/并发编程
-
设计模式
-
-
- 尽管这本书叫做设计模式:重复使用模块,但是我还是认为Head First是对于新手来说很不错的书。
-
-
信息传输, 序列化,和队列化的系统
-
快速傅里叶变换
-
布隆过滤器
- 给一个布隆过滤器m比特和k个哈希函数,所有的注入和相关测试都会是通过。
- 布隆过滤器
- 布隆过滤器 | 数据挖掘 | Stanford University
- 教程
- 如何写一个布隆过滤器应用
-
van Emde Boas 树
-
更深入的数据结构
-
跳表
- "有一种非常迷幻的数据类型" - Skiena
-
网络流
-
不相交集 & 联合查找
-
-
快速处理数学
-
树堆 (Treap)
- 一个二叉搜索树和一个堆的组合
-
线性规划(Linear Programming)(视频)
-
几何:凸包(Geometry, Convex hull)(视频)
-
离散数学
- 查看下面的视频:(这里没看到视频= =)
-
机器学习(Machine Learning)
-
- 课程:
- 资源:
- 书籍: Data Science from Scratch: First Principles with Python: https://www.amazon.com/Data-Science-Scratch-Principles-Python/dp/149190142X
- 网站: Data School: http://www.dataschool.io/
-
-
Go 语言
-
--
一些主题的额外内容
我为前面提到的某些主题增加了一些额外的内容,之所以没有直接添加到前面,是因为这样很容易导致某个主题内容过多。毕竟你想在本世纪找到一份工作,对吧?
视频系列
坐下来享受一下吧。"netflix and skill" 😛