interview
原先我为了成为一个软件工程师而建立这份简单的学习主题清单, 但这份清单随着时间的推移而膨胀成今天这样。在做完这份清单上的每个目标后,我成为了 Amazon 的软件开发工程师! 你或许不需要像我一样学习这么多。但是,让你成为一位称职工程师所需要的知识都在这里了。
我每天自学8~12小时,这样持续了好几个月。这是我的故事:为什么我为了 Google 面试而自学了8个月。
请注意: 你不需要像我一样那么努力学习。我在一些不必要的事情上浪费了很多时间。关于这个问题下面有更多信息。我会帮助你节省宝贵的时间,让你达到目标。 在这份清单内的主题会让你拥有足够的知识去面对几乎每家软件公司的技术面试,包括科技巨头:Amazon、Facebook、Google,以及 Microsoft。
祝你好运!
这是?
这是我为成为一家大公司的软件工程师制定的多月学习计划。
要求:
- 一点编程经验(变量、循环、方法/函数等)
- 耐心
- 时间
注意,这是一份关于 软件工程 的学习计划,而不是前端工程或全栈开发。 这些职业路径有很多详细的路线图和课程资料可以在其他地方找到(请参阅 https://roadmap.sh/ 获取更多信息)。
在大学计算机科学专业中,有很多知识需要学习,但是只掌握大约75%的内容就足够应对面试了,这也是我在这里涵盖的内容。 如果你想进行完整的自学计算机科学项目,可以参考Kamran Ahmed的计算机科学路线图:https://roadmap.sh/computer-science
目录
学习计划
学习的主题
- 算法复杂度 / Big-O / 渐进分析法
- 数据结构
- 更多的知识
- 树(Trees)
- 树-介绍
- 二叉查找树(Binary search trees):BSTs
- 堆(Heap) / 优先级队列(Priority Queue) / 二叉堆(Binary Heap)
- 平衡搜索树 (总体概念,不涉及细节)
- 遍历:前序、中序、后序、BFS、DFS
- 排序
- 选择排序(selection)
- 插入排序(insertion)
- 堆排序(heapsort)
- 快速排序(quicksort)
- 归并排序(merge sort)
- 图(Graphs)
- 有向图(directed)
- 无向图(undirected)
- 邻接矩阵(adjacency matrix)
- 邻接表(adjacency list)
- 遍历:广度优先(BFS), 深度优先(DFS)
- 更多知识
- 最终复习
获得工作机会
---------------- 以下所有内容均为可选项 ----------------
可选的额外主题和资源
- 额外书籍
- 系统设计、可扩展性和数据处理
- 附加学习
- 编译器
- Emacs and vi(m)
- Unix 命令行工具
- 信息论
- 奇偶校验位 & 汉明码 (视频)
- 系统熵值
- 密码学
- 压缩
- 计算机安全
- 垃圾回收
- 并行编程
- 消息传递,序列化和队列化的系统
- A*搜索算法
- 快速傅里叶变换
- 布隆过滤器
- HyperLogLog
- 局部敏感哈希
- van Emde Boas 树
- 增强数据结构
- 平衡查找树
- AVL 树
- 伸缩树(Splay tree)
- 红黑树
- 2-3 查找树
- 2-3-4 树(也称 2-4 树)
- N-ary (K-ary, M-ary)树
- B 树
- k-D 树
- 跳表
- 网络流
- 不相交集 & 联合查找
- 快速处理的数学
- 树堆 (Treap)
- 线性规划
- 几何:凸包(Geometry, Convex hull)
- 离散数学
- 一些主题的额外内容
- 视频系列
- 计算机科学课程
- 论文
为何要用到它?
如果你想在一家大公司担任软件工程师,这些是你必须了解的事情。
如果你错过了计算机科学的学位,就像我一样,这将帮助你迎头赶上,并节省四年的时间。
当我开始这个项目时,我对堆栈和堆没有任何了解, 也不知道大O表示法或者关于树的任何东西,也不知道如何遍历图形。 如果让我编写一个排序算法,相信我它会很糟糕。 我曾经使用过的每种数据结构都是内置在语言中的,并且我完全不知道它们在底层是如何工作的。 除非运行中的进程出现“内存不足”错误,否则我从来没有管理过内存,并且那时候就需要找到一种解决方法。 在我的生活中,我使用过一些多维数组和成千上万个关联数组,但从未从头开始创建数据结构。
这是一个漫长的计划,以至于花费了我数月的时间。若你早已熟悉大部分的知识,那么也许能节省大量的时间。
如何使用它
下面所有的东西都只是一个概述。因此,你需要由上而下逐一地去处理它。
在学习过程中,我使用 GitHub 特殊语法的 Markdown 去检查计划的进展,包括使用包含任务进度的任务列表。
如果你不想使用 Git
在该页面上,单击顶部附近的 Code 按钮,然后单击“Download ZIP”。解压文件,就可以使用文本文件了。
如果你打开一个代码编辑器,你会看到所有格式都很好。
如果你不介意 Git
创建一个新的分支,这样你就可以检查类似这样的项目了,只需在方括号中放入一个x:[x]
在 GitHub 上 Fork 该仓库: 点击 Fork 按钮,将
https://github.com/jwasham/coding-interview-university
仓库复制到你的 GitHub 账号中。克隆项目到本地:
git clone git@github.com:<your_github_username>/coding-interview-university.git cd coding-interview-university git remote add upstream https://github.com/jwasham/coding-interview-university git remote set-url --push upstream DISABLE # 这样你就不会将个人进展推回到原始仓库了。
在你完成了一些修改后,在框框中打 x:
git commit -am "Marked personal progress" git pull upstream main # 将您的分支与原始仓库中的更改保持最新 git push # just pushes to your fork
不要觉得自己不够聪明
- 大多数成功的软件工程师都非常聪明,但他们都有一种觉得自己不够聪明的不安全感。
- 下面的视频可以帮助你克服这种不安全感:
相关视频资源
部分视频只能通过在 Coursera 或者 Edx 课程上注册登录才能观看。 这些视频被称为网络公开课程(MOOC)。有时候某些课程需要等待好几个月才能获取,这期间你无法观看这些课程的影片。
很感谢你能帮我把网络公开课程的视频链接转换成公开的,可持续访问的视频源, 比如 YouTube 视频,以代替那些在线课程的视频。 此外,一些大学的讲座视频也是我所青睐的。
选择编程语言
你需要为你做的编程面试选择一种编程语言, 但你也需要找到一种可以用来学习计算机科学概念的语言。
最好是同一种语言,这样你只需精通其中一种。
对于这个学习计划
在这个学习计划中,我主要使用了两种编程语言:C和Python。
- C: 非常底层。它允许你处理指针和内存的分配与释放,因此你能够深入理解数据结构和算法。 在像Python或Java这样的高级语言中,这些细节被隐藏起来。在日常工作中,这是很好的, 但当你学习这些底层数据结构时,感受它们与计算机硬件的联系也是非常有益的。
- C 语言无处不在。在你学习的过程中,你会在书籍、讲座、视频以及任何地方看到C语言的例子。
- 《C程序设计语言(第2版)》
- 这是一本简短的书,但它会让你很好地掌握C语言,只要稍微练习一下, 你很快就能熟练使用。理解C语言有助于你了解程序和内存是如何工作的。
- 你不需要深入研究这本书(甚至不用读完它)。只要阅读到你感觉舒服,并能写一些C语言的代码就可以了。
- 书中问题的答案
- Python: 现代且非常灵活,我学习它是因为它非常实用,同时在面试中也能让我写更少的代码。
这是我的个人喜好,当然你可以根据自己的偏好来选择。
也许你并不需要,但以下是一些学习新编程语言的网站:
对于你的编程面试
你可以在编程这一环节,使用一种自己用起来较为舒适的语言去完成编程,但对于大公司,你只有三种固定的选择:
- C++
- Java
- Python
你也可以使用下面两种编程语言,但可能会有某些限制,你需要事先查明:
- JavaScript
- Ruby
这是我写的一篇关于选择面试语言的文章: 为编程面试选择一种语言。 这是我发布帖子所基于的原始文章: Choosing a Programming Language for Interviews
你需要对你所选择的语言感到非常舒适且足够了解。
更多关于语言选择的阅读:
数据结构和算法的书籍
这本书将为你的计算机科学打下基础。
只需选择一种你感到舒适的语言。你将会进行大量阅读和编码工作。
C
- C语言中的算法,第1-5部分(捆绑包),第3版
- 基础知识,数据结构,排序,搜索和图算法
Python
- 作者:Goodrich、Tamassia、Goldwasser
- 我非常喜爱这本书,它包含了所有东西
- 很 Python 的代码
- 我的读书报告:https://startupnextdoor.com/book-report-data-structures-and-algorithms-in-python/
Java
你的选择:
- Goodrich, Tamassia, Goldwasser
- Sedgewick and Wayne:
C++
你的选择:
- Goodrich, Tamassia, and Mount
- Sedgewick and Wayne
面试准备书籍
你不需要买一堆这些。老实说,《破解编程面试》可能已经足够了, 但我买了更多来给自己更多的练习。但我总是做得太多。
这两个都是我买的,他们给了我大量的练习。
- Programming Interviews Exposed: Coding Your Way Through the Interview, 4th Edition
- 提供C++和Java语言的答案
- 这本书是准备《Cracking the Coding Interview》的很好热身书
- 难度适中。大多数问题可能比实际面试中遇到的问题要简单(根据我所读的内容)
- Cracking the Coding Interview, 6th Edition
- 提供Java语言的答案
如果你有很多额外的时间:
选择一个:
- Elements of Programming Interviews (C++ version)
- Elements of Programming Interviews in Python
- Elements of Programming Interviews (Java version) - 配套项目-本书中每个问题的方法存根和测试用例
不要犯我的错误
这个列表在很多个月里不断增长,是的,它变得失控了。
以下是我犯过的一些错误,这样你就能有更好的体验。而且你将节省数月时间。
1. 你不可能把所有的东西都记住
我看了数小时的视频并做了大量笔记,几个月后有很多东西我都不记得了。 我花了三天时间浏览我的笔记并制作闪卡,以便进行复习。其实,并不需要那么多知识。
请阅读以下的文章以免重蹈覆辙:
2. 使用抽认卡
为了解决善忘的问题,我制作了一个抽认卡的网页,用于添加两种抽认卡:一般的及带有代码的。每种卡都会有不同的格式设计。 而且,我还以移动设备为先去设计这些网页,以使得在任何地方,我都能通过我的手机及平板去回顾知识。
你也可以免费制作属于你自己的抽认卡网站:
我不建议使用我的闪卡。它们太多了,而且大部分都是你不需要的琐事。
但是如果你不想听我的话,那就随你吧:
有一点需要记住的是,我做事有点过头,以至于卡片都覆盖到所有的东西上,从汇编语言和 Python 的细枝末节,到机器学习和统计都被覆盖到卡片上。 而这种做法,对于要求来说是多余的。
在抽认卡上做笔记: 若你第一次发现你知道问题的答案时,先不要急着把其标注成“已知”。 反复复习这张抽认卡,直到每次都能答对后才是真正学会了这个问题。 反复地问答可帮助你深刻记住该知识点。
这里有个替代我抽认卡的网站 Anki,很多人向我推荐过它。 这个网站用同一个字卡重复出现的方式让你牢牢地记住知识。 这个网站非常容易使用,支持多平台,并且有云端同步功能。在 iOS 平台上收费25美金,其他平台免费。
这是我用 Anki 这个网站里的格式所储存的抽认卡资料库: https://ankiweb.net/shared/info/25173560 (感谢 @xiewenya)。
一些学生提到了关于空白间距的格式问题,可以通过以下方法进行修复:打开卡片组,编辑卡片,点击"卡片"选项,选择"样式"单选按钮,在卡片类中添加成员 "white-space: pre;"。
3. 在学习过程中做编程面试题
这非常重要。
在学习数据结构和算法的同时,开始做编程面试题。
你需要将所学知识应用于解决问题,否则你会忘记。我曾经犯过这个错误。
一旦你学完一个主题,并且对它有了一定的掌握,比如 链表(linked lists):
- 打开其中一本编程面试书籍(或下方列出的编程问题网站之一)。
- 请先做2或3个关于链表的问题。
- 继续学习下一个主题。
- 稍后,回来再做另外2或3个链表问题。
- 使用这种方法来学习每个新主题。
在学习这些内容的过程中不断做问题,而不是之后。
你被雇佣的不是因为你的知识,而是因为你知道如何应用这些知识。
下面列出了许多资源供你参考。继续前进吧。
4. 专注
在学习的过程中,往往会有许多令人分心的事占据着我们宝贵的时间。 因此,专注和集中注意力是非常困难的。放点纯音乐能帮上一些忙。
没有包含的内容
有一些熟悉且普遍的技术在此未被谈及到:
- Javascript
- HTML,CSS和其他前端技术
- SQL
日常计划
这门课涵盖了很多主题。每个主题可能需要你几天的时间,甚至可能需要一周或更长时间。这取决于你的日程安排。
每天,按照列表中的下一个主题,观看一些关于该主题的视频, 然后用你选择的语言为这门课程编写该数据结构或算法的实现。
在这里你可以查看到我的代码:
你不需要记住每个算法。你只需要能够理解它,以便能够编写自己的实现即可。
编程问题练习
这是为什么?我还没有准备好面试。
为什么你需要练习编程问题:
- 识别问题,并确定合适的数据结构和算法
- 收集问题的要求
- 像在面试中那样口头表达解决问题的过程
- 在白板或纸上编写代码,而不是在计算机上
- 为您的解决方案确定时间和空间复杂度(参见下文中的大O表示法)。
- 对你的解决方案进行测试
在面试中,有一种方法论的、有交流的问题解决方法。你可以从编程面试书籍中了解这些, 但我发现下面这个网站也非常出色: 算法设计画布
在白板或纸上写代码,而不是在计算机上。使用一些样例输入进行测试。然后在计算机上键入并进行测试。
如果家里没有白板,请从艺术用品店购买一个大型的绘图本。 你可以坐在沙发上练习。这就是我的"沙发白板"。照片中我加了一支笔来衡量尺寸。如果你使用钢笔,你会希望能擦除。 会很快变得凌乱, 我用铅笔和橡皮擦。
编程问题练习并不是为了记住解决编程问题的答案。
编程问题
别忘了参考你的主要编程面试书籍这里.
解决问题:
编程面试问题视频:
- IDeserve(88个视频)
- Tushar Roy(5个播放列表)
- 非常适合问题解决方案的演示
- Nick White - LeetCode解答(187个视频)
- 解释解决方案和代码的很好
- 你可以在短时间内观看多个视频
- FisherCoder - LeetCode解答
挑战/练习网站:
- LeetCode
- 我最喜欢的编程问题网站。对于你准备的1-2个月时间,订阅会费是值得的。
- 观看上面提到的Nick White和FisherCoder的视频,可以帮助你理解代码解决方案。
- HackerRank
- TopCoder
- Codeforces
- Codility
- Geeks for Geeks
- AlgoExpert
- 由谷歌工程师创建,也是提高你技能的优秀资源。
- Project Euler
- 主要关注数学问题,并不完全适合编程面试。
让我们开始吧
好了,说得够多了,让我们学习吧!
但在学习的同时,不要忘记做上面的编码问题!
算法复杂度 / Big-O / 渐进分析法
- 这里没有什么需要实施的,你只是在观看视频并记笔记!耶!
- 这里有很多视频,只要看到你理解为止就好了,你随时可以回来复习。
- 如果你不理解背后的所有数学,不要担心。
- 你只需要理解如何用大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) - 如果键已存在,则更新值
- exists(key) - 检查键是否存在
- get(key) - 获取给定键的值
- remove(key) - 删除给定键的值
更多的知识
二分查找(Binary search)
- 二分查找(在一个已排序好的整型数组中查找)
- 迭代式二分查找
按位运算(Bitwise operations)
树(Trees)
树-介绍
- BFS 笔记
- 层次遍历(BFS,使用队列)
- 时间复杂度: O(n)
- 空间复杂度:最佳情况:O(1),最坏情况:O(n/2)=O(n)
- DFS 笔记:
- 时间复杂度:O(n)
- 空间复杂度:
- 最好情况:O(log n) - 树的平均高度
- 最坏情况:O(n)
- 中序遍历(DFS:左、节点本身、右)
- 后序遍历(DFS:左、右、节点本身)
- 先序遍历(DFS:节点本身、左、右)
- BFS 笔记
二叉查找树(Binary search trees):BSTs
- C/C++:
- C/C++:
堆(Heap) / 优先级队列(Priority Queue) / 二叉堆(Binary Heap)
- 以树形结构可视化,但通常在存储上是线性的(数组、链表)
排序(Sorting)
- 实现各种排序,知道每种排序的最坏、最好和平均的复杂度分别是什么场景:
- 不要用冒泡排序 - 效率太差 - 时间复杂度 O(n^2), 除非 n <= 16
- 并不推荐对一个链表排序,但归并排序是可行的.
- 链表的归并排序
- 实现各种排序,知道每种排序的最坏、最好和平均的复杂度分别是什么场景:
关于堆排序,请查看前文堆的数据结构部分。堆排序很强大,不过是非稳定排序。
- 选择排序和插入排序的最坏、平均时间复杂度都是 O(n^2)。
- 关于堆排序,请查看前文堆的数据结构部分。
总结一下,这是15种排序算法的可视化表示。 如果你需要有关此主题的更多详细信息,请参阅“一些主题的额外内容”中的“排序”部分。
图(Graphs)
图表可以用来表示计算机科学中的许多问题,所以这一部分很长,就像树和排序一样。
笔记:
- 有4种基本方式在内存里表示一个图:
- 对象和指针
- 邻接矩阵
- 邻接表
- 邻接图
- 熟悉以上每一种图的表示法,并了解各自的优缺点
- 广度优先搜索和深度优先搜索:知道它们的计算复杂度和设计上的权衡以及如何用代码实现它们
- 遇到一个问题时,首先尝试基于图的解决方案,如果没有再去尝试其他的。
- 有4种基本方式在内存里表示一个图:
MIT(视频):
完整的 Coursera 课程:
我会实现:
- 基于 DFS 的算法 (根据上文 Aduni 的视频):
- 基于 DFS 的算法 (根据上文 Aduni 的视频):
更多知识
递归(Recursion)
- 什么时候适合使用
- 尾递归会更好么?
动态规划(Dynamic Programming)
- 在你的面试中或许没有任何动态规划的问题, 但能够知道一个题目可以使用动态规划来解决是很重要的。
- 这一部分会有点困难,每个可以用动态规划解决的问题都必须先定义出递推关系,要推导出来可能会有点棘手。
- 我建议先阅读和学习足够多的动态规划的例子,以便对解决 DP 问题的一般模式有个扎实的理解。
设计模式
- I know the canonical book is "Design Patterns: Elements of Reusable Object-Oriented Software", but Head First is great for beginners to OO.
- Handy reference: 101 Design Patterns & Tips for Developers
组合(Combinatorics) (n 中选 k 个) & 概率(Probability)
- 课程设置:
- 只有视频 - 41 (每一个都短小精悍):
- 课程设置:
NP, NP-Completeness和近似算法
- 知道最经典的一些 NP-Completeness 问题,比如旅行商问题和背包问题, 而且能在面试官试图忽悠你的时候识别出他们。
- 知道 NP-Completeness 是什么意思.
- Peter Norvik 讨论旅行商问题的近似最优解:
- 《算法导论》(CLRS)的第 1048 - 1140 页。
计算机如何处理程序
缓存(Cache)
进程(Processe)和线程(Thread)
- 视频 1-11 是关于进程和线程
- 操作系统和系统编程(视频)
- 进程和线程的区别是什么?
- 涵盖了:
- 进程、线程、协程
- 进程和线程的区别
- 进程
- 线程
- 锁
- 互斥
- 信号量
- 监控
- 他们是如何工作的
- 死锁
- 活锁
- CPU 活动, 中断, 上下文切换
- 现代多核处理器的并发式结构
- 分页(paging),分段(segmentation)和虚拟内存(视频)
- 中断(视频)
- 进程资源需要(内存:代码、静态存储器、栈、堆、文件描述符、I/O)
- 线程资源需要(在同一个进程内和其他线程共享以上(除了栈)的资源,但是每个线程都有独立的程序计数器、栈计数器、寄存器和栈)
- Fork 操作是真正的写时复制(只读),直到新的进程写到内存中,才会生成一份新的拷贝。
- 上下文切换
- 进程、线程、协程
测试
- 涵盖了:
- 单元测试是如何工作的
- 什么是模拟对象
- 什么是集成测试
- 什么是依赖注入
- 涵盖了:
字符串搜索和操作
如果你需要有关此主题的更多详细信息,请参阅“一些主题的额外内容”中的“字符串匹配”部分。
字典树(Tries)
- 需要注意的是,字典树各式各样。有些有前缀,而有些则没有。有些使用字符串而不使用比特位来追踪路径。
- 阅读代码,但不实现。
- Sedgewick──字典树(3个视频)
浮点数
Unicode
字节序(Endianness)
- 大/小端序
- 大端序 Vs 小端序(视频)
- 由里入内的大端序与小端序(视频)
- 对于内核开发非常具有技术性,如果大多数的内容听不懂也没关系。
- 前半部就已经足够了。
网络(视频)
- 如果你具有网络经验或想成为可靠性工程师或运维工程师,期待你的问题
- 知道这些有益无害,多多益善!
最终复习
本节将包含一系列短视频,您可以迅速观看,以便复习大部分重要概念。
如果您经常需要温习知识,这会很有帮助。
更新你的简历
- 在书籍《Cracking The Coding Interview》和《Programming Interviews Exposed》中查看简历准备信息。
- “这就是一个优秀简历的样子” by Gayle McDowell(《Cracking the Coding Interview》的作者),
- 作者备注:“这是针对美国的简历。印度和其他国家的简历有不同的期望,尽管许多要点是相同的。”
- “逐步简历指南” by Tech Interview Handbook
- 详细指南,教您如何从零开始设置您的简历,编写有效的简历内容,优化它,并测试您的简历。
面试流程与一般面试准备
- 面试准备课程:
- 数据结构、算法和面试的Python课程(付费课程)::
- 以Python为中心的面试准备课程,涵盖数据结构、算法、模拟面试等内容。
- 使用Python的数据结构和算法简介(Udacity免费课程)::
- 一个免费的以Python为中心的数据结构和算法课程。
- 数据结构和算法纳米学位!(Udacity付费纳米学位)::
- 提供超过100个数据结构和算法练习的实际操作体验,并得到专属导师的指导,以帮助您为面试和实际工作做准备。
- Grokking行为面试(Educative免费课程)::
- 很多时候,阻碍您获得梦想工作的不是您的技术能力,而是您在行为面试中的表现。
- AlgoMonster(付费课程,提供免费内容):):
- LeetCode的速成课程。涵盖了从成千上万的问题中提炼出的所有模式。
- 数据结构、算法和面试的Python课程(付费课程)::
模拟面试:
- Gainlo.co:来自大公司的模拟面试官 - 我用过这个,帮助我放松进行电话和现场面试。
- Pramp:与同行进行模拟面试 - 同行模式的实践面试。
- interviewing.io:与资深工程师进行模拟面试 - 匿名算法/系统设计面试,与FAANG公司的资深工程师进行。
- Meetapro:与顶级FAANG面试官进行模拟面试 - 类似Airbnb的模拟面试/指导平台。
- Hello Interview:与专家教练和人工智能模拟面试 - 直接与人工智能或 FAANG 员工工程师和经理面试。
- Codemia:通过人工智能或社区解决方案和反馈来练习系统设计问题 - 通过AI练习工具来解决系统设计问题。与社区分享你的解决方案,以获得反馈。.
当面试来临的时候
随着下面列举的问题思考下你可能会遇到的 20 个面试问题,每个问题准备 2-3 种回答。 准备点故事,不要只是摆一些你完成的事情的数据,相信我,人人都喜欢听故事。
- 你为什么想得到这份工作?
- 你解决过的最有难度的问题是什么?
- 面对过的最大挑战是什么?
- 见过的最好或者最坏的设计是怎么样的?
- 对某个产品提出改进建议。
- 你作为一个个体同时也是团队的一员,如何达到最好的工作状态?
- 你的什么技能或者经验是你的角色中不可或缺的,为什么?
- 你在某份工作或某个项目中最享受的是什么?
- 你在某份工作或某个项目中面临过的最大挑战是什么?
- 你在某份工作或某个项目中遇到过的最硬的 Bug 是什么样的?
- 你在某份工作或某个项目中学到了什么?
- 你在某份工作或某个项目中哪些地方还可以做的更好?
问面试官的问题
我会问的一些:(可能我已经知道了答案但我想听听面试官的看法或者了解团队的前景):
- 团队多大规模?
- 开发周期是怎样的? 会使用瀑布流/极限编程/敏捷开发么?
- 经常会为截止日期(deadlines)加班么? 或者是有弹性的?
- 团队里怎么做技术选型?
- 每周平均开多少次会?
- 你觉得工作环境有助于员工集中精力吗?
- 目前正在做什么工作?
- 喜欢这些事情吗?
- 工作期限是怎么样的?
- 工作生活怎么平衡?
当你获得了梦想的职位
恭喜你!
继续学习。
活到老,学到老。
*****************************************************************************************************
*****************************************************************************************************
下面的内容都是可选的。
通过学习这些内容,你将会得到更多的有关 CS 的概念,并将为所有的软件工程工作做更好的准备。
你将会成为一个更全面的软件工程师。
*****************************************************************************************************
*****************************************************************************************************
额外书籍
你可以从以下的书单挑选你有兴趣的主题来研读。
- UNIX环境高级编程
- 老,但却很棒
- Linux 命令行大全
- 现代选择
- TCP-IP详解系列
- Head First 设计模式
- 设计模式入门介绍
- 设计模式:可复用面向对象软件的基础
- 也被称为“四人帮”(Gang of Four(GOF))
- 经典设计模式书籍
- 算法设计手冊(Skiena)
- 算法 (Jeff Erickson)
- 编程卓越之道(第一卷):深入理解计算机
- 该书于2004年出版,虽然有些过时,但是对于简单了解计算机而言,这是一个了不起的资源
- 作者发明了高阶组合语言 HLA,所以提到,并且举了一些HLA的例子。里面没有用到很多,但都是很棒的组合语言的例子。
- 这些章节值得阅读,为你提供良好的基础:
- 第2章──数字表示
- 第3章──二进制算术和位运算
- 第4章──浮点表示
- 第5章──字符表示
- 第6章──内存组织和访问
- 第7章──组合数据类型和内存对象
- 第9章──CPU体系结构
- 第10章──指令集架构
- 第11章──内存体系结构和组织
- 算法导论
- 重要提示:读这本书的价值有限。本书很好地回顾了算法和数据结构,但不会教你如何编写良好的代码。你必须能够有效地编写一个不错的解决方案
- 又称 CLR,有时是 CLRS,因为 Stein 最后才加入
- 计算机体系结构,第六版:定量方法
- 对于更丰富、更时新(2017年)但较长的处理方式
系统设计、可扩展性和数据处理
如果您有4年以上的工作经验,可以预期会遇到系统设计问题。
- 可扩展性和系统设计是一个非常广泛的主题,涵盖了许多内容和资源, 因为在设计一个可以扩展的软件/硬件系统时需要考虑很多因素。 预计需要花费相当多的时间来学习这方面的知识。
- 考虑要点:
- 可扩展性
- 将大数据集归纳为单一值
- 将一个数据集转换为另一个数据集
- 处理海量数据
- 系统设计
- 功能集
- 接口
- 类层次结构
- 在特定约束下设计系统
- 简单性和鲁棒性
- 权衡
- 性能分析和优化
- 可扩展性
- 您不需要掌握所有这些内容,只需选择一些您感兴趣的。
- 欲知更多信息,请参阅Video Series 部分中的“Mining Massive Datasets”视频系列
- 复习: The System Design Primer
- HiredInTech的系统设计
- 速查表
- 流程:
- 理解问题和范围:
- 定义用例,与面试官的帮助
- 提出额外的功能
- 移除面试官认为超出范围的项目
- 假设需要高可用性,并将其添加为用例
- 考虑限制:
- 询问每月有多少个请求
- 询问每秒有多少个请求(他们可能会主动提供或让您计算)
- 估计读取与写入的百分比
- 保持估计时考虑80/20法则
- 每秒写入多少数据
- 在5年内所需的总存储量
- 每秒读取多少数据
- 抽象设计:
- 层(服务、数据、缓存)
- 基础架构:负载均衡、消息传递
- 驱动服务的任何关键算法的粗略概述
- 考虑瓶颈并确定解决方案
- 理解问题和范围:
- 练习:
附加学习
我把它们加进来是为了让你成为更全方位的软件工程师,并且留意一些技术以及算法,让你拥有更大的工具箱。
编译器
Emacs and vi(m)
- 熟悉基于 unix 的代码编辑器
- vi(m):
- emacs:
- Emacs 绝对初学者指南(David Wilson的视频)
- Emacs 绝对初学者指南(David Wilson 批注)
Unix 命令行工具
信息论 (视频)
- Khan Academy 可汗学院
- 更多有关马尔可夫的内容:
- 关于更多信息,请参照下方 MIT 6.050J 信息和系统复杂度的内容。
奇偶校验位 & 汉明码 (视频)
系统熵值(Entropy)
- 请参考下方视频
- 观看之前,请先确定观看了信息论的视频
- 信息理论, 克劳德·香农, 熵值, 系统冗余, 数据比特压缩 (视频)
密码学
压缩
- 观看之前,请先确定观看了信息论的视频
- Computerphile (视频):
- 数据压缩的艺术
- (可选) 谷歌开发者:GZIP 还差远了呢!
计算机安全
垃圾回收
并行编程
消息传递,序列化和队列系统
A*搜索算法
快速傅里叶变换
布隆过滤器
- 给定布隆过滤器m比特位和k个哈希函数,插入和成员检测都会是 O(k)。
- 布隆过滤器(视频)
- 布隆过滤器 | 数据挖掘 | Stanford University(视频)
- 教程
- 如何写一个布隆过滤器应用
HyperLogLog
局部敏感哈希
- 用于确定文件的相似性
- MD5 或 SHA 的反义词,用于确定2个文档/字符串是否完全相同
- Simhashing(希望如此)变得简单
van Emde Boas 树
增强数据结构
平衡查找树(Balanced search trees)
掌握至少一种平衡查找树(并懂得如何实现):
“在各种平衡查找树当中,AVL 树和2-3树已经成为了过去,而红黑树(red-black trees)看似变得越来越受人青睐。 这种令人特别感兴趣的数据结构,亦称伸展树(splay tree)。 它可以自我管理,且会使用轮换来移除任何访问过根节点的键。” —— Skiena
因此,在各种各样的平衡查找树当中,我选择了伸展树来实现。 虽然,通过我的阅读,我发现在面试中并不会被要求实现一棵平衡查找树。 但是,为了胜人一筹,我们还是应该看看如何去实现。在阅读了大量关于红黑树的代码后, 我才发现伸展树的实现确实会使得各方面更为高效。
- 伸展树:插入、查找、删除函数的实现,而如果你最终实现了红黑树,那么请尝试一下:
- 跳过删除函数,直接实现搜索和插入功能
我希望能阅读到更多关于 B 树的资料,因为它也被广泛地应用到大型的数据集当中。
AVL 树
- 实际中: 我能告诉你的是,该种树并无太多的用途,但我能看到有用的地方在哪里: AVL 树是另一种平衡查找树结构。其可支持时间复杂度为 O(log n) 的查询、插入及删除。 它比红黑树严格意义上更为平衡,从而导致插入和删除更慢,但遍历却更快。正因如此,才彰显其结构的魅力。 只需要构建一次,就可以在不重新构造的情况下读取, 适合于实现诸如语言字典(或程序字典,如一个汇编程序或解释程序的操作码)。
- MIT AVL 树 / AVL 树的排序(视频)
- AVL 树(视频)
- AVL 树的实现(视频)
- 分离与合并
- [Review] AVL Trees (playlist) in 19 minutes (video)
伸展树
- 实际中: 伸展树一般用于缓存、内存分配者、路由器、垃圾回收者、数据压缩、ropes (字符串的一种替代品,用于存储长串的文本字符)、 Windows NT(虚拟内存、网络及文件系统)等的实现。
- CS 61B:伸展树(Splay trees)(视频)
- MIT 教程:伸展树(Splay trees):
- 该教程会过于学术,但请观看到最后的10分钟以确保掌握。
- 视频
红黑树
- 这些是2-3棵树的翻译(请参见下文)。
- 实际中:红黑树提供了在最坏情况下插入操作、删除操作和查找操作的时间保证。 这些时间值的保障不仅对时间敏感型应用有用,例如实时应用, 还对在其他数据结构中块的构建非常有用, 而这些数据结构都提供了最坏情况下的保障; 例如,许多用于计算几何学的数据结构都可以基于红黑树, 而目前 Linux 内核所采用的完全公平调度器(the Completely Fair Scheduler)也使用到了该种树。 在 Java 8中,Collection HashMap也从原本用Linked List实现, 储存特定元素的哈希码,改为用红黑树实现。
- Aduni —— 算法 —— 课程4(该链接直接跳到开始部分)(视频)
- Aduni —— 算法 —— 课程5(视频)
- 黑树(Black Tree)
- 二分查找及红黑树的介绍
- [Review] Red-Black Trees (playlist) in 30 minutes (video)
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树(视频)
N 叉树(K 叉树、M 叉树)
- 注意:N 或 K 指的是分支系数(即树的最大分支数):
- 二叉树是一种分支系数为2的树
- 2-3树是一种分支系数为3的树
- K 叉树
B 树
- 有趣的是:为啥叫 B 仍然是一个神秘。因为 B 可代表波音(Boeing)、平衡(Balanced)或 Bayer(联合创造者)
- 实际中: B 树会被广泛适用于数据库中,而现代大多数的文件系统都会使用到这种树(或变种)。 除了运用在数据库中,B 树也会被用于文件系统以快速访问一个文件的任意块。 但存在着一个基本的问题, 那就是如何将文件块 i 转换成一个硬盘块(或一个柱面-磁头-扇区)上的地址。
- B 树
- B 树数据结构
- B 树的介绍(视频)
- B 树的定义及其插入操作(视频)
- B 树的删除操作(视频)
- MIT 6.851 —— 内存层次模块(Memory Hierarchy Models)(视频)
- 覆盖有高速缓存参数无关型(cache-oblivious)B 树和非常有趣的数据结构
- 头37分钟讲述的很专业,或许可以跳过(B 指块的大小、即缓存行的大小)
- [Review] B-Trees (playlist) in 26 minutes (video)
k-D树
- 非常适合在矩形或更高维度的对象中查找点数
- 最适合k近邻
- kNN K-d树算法(视频)
跳表
- "有一种非常迷幻的数据类型" - Skiena
- 随机化: 跳表 (视频)
- 更生动详细的解释
网络流
不相交集 & 联合查找
快速处理的数学
树堆 (Treap)
- 一个二叉搜索树和一个堆的组合
- 树堆
- 数据结构:树堆的讲解(视频)
- 集合操作的应用(Applications in set operations)
线性规划(Linear Programming)(视频)
几何:凸包(Geometry, Convex hull)(视频)
离散数学
一些主题的额外内容
我添加了这些内容来加强上面已经提出的一些观点,但是不想把它们放在上面,因为那样会太多。
对于一个主题来说,过度处理很容易。
你希望在本世纪被雇佣吗?
SOLID
Union-Find
动态规划的更多内容 (视频)
图形处理进阶 (视频)
MIT 概率论 (过于数学,进度缓慢,但这对于数学的东西却是必要之恶) (视频):
字符串匹配
- Rabin-Karp(视频)
- Knuth-Morris-Pratt (KMP):
- Boyer–Moore 字符串搜索算法
- Coursera:字符串算法
- 刚开始时很棒,但是当它超过 KMP 时,它变得比需要复杂得多
- 很好的字典树解释
- 可以跳过
排序
- 斯坦福大学关于排序算法的视频:
- Shai Simonson 视频,Aduni.org:
- Steven Skiena 关于排序的视频:
NAND 到 Tetris: 从第一原理构建现代计算机
视频系列
坐下来,尽情享受。
计算机科学课程
算法实现
论文
- 喜欢经典的论文?
- 1978: 通信顺序处理
- 2003: The Google 文件系统
- 2012 年被 Colossus 取代了
- 2004: MapReduce: Simplified Data Processing on Large Clusters
- 大多被云数据流取代了?
- 2006年:Bigtable:结构化数据的分布式存储系统
- 2006年:针对松散耦合的分布式系统的Chubby Lock服务
- 2007年:Dynamo:亚马逊的高可用键值存储
- Dynamo论文启动了NoSQL革命
- 2007: 每个程序员都应该知道的内存知识 (非常长,作者建议跳过某些章节来阅读)
- 2012: AddressSanitizer: 快速的内存访问检查器:
- 2013: Spanner: Google 的分布式数据库:
- 2015: Google的持续流水线
- 2015: 大规模高可用性:构建Google广告数据基础设施
- 2015: 开发人员如何搜索代码:一个案例研究
- 更多论文: 1,000篇论文