自学编程清单(需要自备梯子)

0 / 2266

Coding Interview University

原先我为了成为一个软件工程师而建立这份简单的学习主题清单, 但这份清单随着时间而膨胀成今天这样。在做完这份清单上的每个目标后,我成为了 Amazon 的软件开发工程师! 你或许不需要像我一样学习这么多。但是,让你成为一位称职工程师所需要的知识都在这里了。

我每天自学8~12小时,这样持续了好几个月。这是我的故事:为什么我为了 Google 面试而自学了8个月

在这份清单内的主题会让你拥有足够的知识去面对几乎每家软件公司的技术面试,包括科技巨头:Amazon、Facebook、Google,以及 Microsoft。

祝你好运!

这是?

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

白板上编程 ———— 来自 HBO 频道的剧集,“硅谷”

这份清单适用于 新手软件工程师,或者想从软件/网站开发转向软件工程(需要计算机科学知识)的人员。如果你有多年的经验,并且声称拥有多年的软件工程经验,并且期待一次更艰难的面试。

如果你具有多年的软件/网页开发经验,请注意,大型软件公司(例如 Google,Amazon,Facebook 和 Microsoft)将软件工程视为不同于软件/网页开发,并且它们需要计算机科学知识。

如果你想成为可靠性工程师或运维工程师,请从可选列表(网络,安全)中学习更多。


目录

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


为何要用到它?

当我开始这个项目时,我不知道堆和栈的区别,不了解时间复杂度(Big-O)、树,或如何去遍历一个图。如果非要我去编写一个排序算法的话,我只能说我所写的肯定是很糟糕。一直以来,我所用的任何数据结构都是内建于编程语言当中。至于它们在背后是如何运作,对此我一概不清楚。此外,以前的我并不需要对内存进行管理,最多就只是在一个正在执行的进程抛出了“内存不足”的错误后,才会去找解决方法。在我的编程生涯中,虽然我有用过多维数组,也用过关联数组成千上万次,但我从来没有自己实现过数据结构。

这是一个漫长的计划,以至于花费了我数月的时间。若你早已熟悉大部分的知识,那么也许能节省大量的时间。

如何使用它

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

在学习过程中,我使用 GitHub 特殊语法的 markdown 去检查计划的进展,包括使用包含任务进度的任务列表。

创建一个新的分支,以便你可以像这样去勾选计划的进展:直接往方括号中填写一个字符 x 即可:[x]

Fork一个分支,并跟随以下的指令

通过单击 Fork 按钮来 fork GitHub 仓库:jwasham/coding-interview-university

克隆项目到本地

git checkout -b progress

git remote add jwasham https://github.com/jwasham/coding-interview-university

git fetch --all

在你完成了一些修改后,在框框中打 x

git add .

git commit -m "Marked x"

git rebase jwasham/main

git push --set-upstream origin progress

git push --force

更多关于 Github-flavored markdown 的详情

不要觉得自己不够聪明

相关视频资源

部分视频只能通过在 Coursera 或者 Edx 课程上注册登录才能观看。这些视频被称为网络公开课程(MOOC)。有时候某些课程需要等待好几个月才能获取,这期间你无法观看这些课程的影片。

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

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

为你的面试选择一种语言

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

  • C++
  • Java
  • Python

你也可以使用下面两种编程语言,但可能会有某些限制,你需要实现查明:

  • JavaScript
  • Ruby

我之前写过一篇关于在面试时选择编程语言的文章:为编程面试选择一种语言

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

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

在此查看相关语言的资源

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

书单

为了节省你的时间,以下是比我使用过的更缩减的书单。

面试准备

如果你有额外的时间:

选择以下之一:

编程语言精选

你需要选择面试语言(请参见上文)。

这是我按语言给出的建议。我没有所有语言的资源,欢迎贡献。

如果你通读其中之一,你应该具备了开始解决编程问题所需的所有数据结构和算法知识。除非你需要复习,否则你可以跳过此项目中的所有视频讲座

额外编程语言的精选资源

C++

我没有读过这两本书,但是它们颇受好评,作者是 Sedgewick,他非常厉害。

如果你有更好的 C++ 书籍,请告诉我。我正在搜集全面的资源。

Java

或者:

  • Java 数据结构和算法
    • 作者:Goodrich、Tamassia、Goldwasser
    • 用作 UC Berkeley 的 CS 入门课程的可选教材
    • 请参阅下面有关 Python 版本的我的读书报告,这本书涵盖了相同的主题

Python

在你开始之前

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

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

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

就算我观看了数小时的视频,并记录了大量的笔记,几个月后的我,仍然会忘却其中大部分的东西。所以,我花了3天翻阅我的笔记,并制作成抽认卡(flashcard)帮助我复习:

请阅读以下的文章以免重蹈覆辙:

记住计算机科学知识

有人推荐给我的课程(但我还沒看过):学习如何学习

2. 使用抽认卡

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

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

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

有一点需要记住的是,我做事有点过头,以至于卡片都覆盖到所有的东西上,从汇编语言和 Python 的细枝末节,到机器学习和统计都被覆盖到卡片上。而这种做法,对于要求来说是多余的。

在抽认卡上做笔记: 若你第一次发现你知道问题的答案时,先不要急着把其标注成“已知”。反复复习这张抽认卡,直到每次都能答对后才是真正学会了这个问题。反复地问答可帮助你深刻记住该知识点。

这里有个替代我抽认卡的网站 Anki,很多人向我推荐过它。这个网站用同一个字卡重复出现的方式让你牢牢地记住知识。这个网站非常容易使用,支持多平台,并且有云端同步功能。在 iOS 平台上收费25美金,其他平台免费。

这是我用 Anki 这个网站里的格式所储存的抽认卡资料库: ankiweb.net/shared/info/25173560 (感谢 @xiewenya

3. 复习,复习,再复习

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

编程累了就休息半个小时,并去复习你的抽认卡。

4. 专注

在学习的过程中,往往会有许多令人分心的事占据着我们宝贵的时间。因此,专注和集中注意力是非常困难的。放点纯音乐能帮上一些忙。

没有包含的内容

有一些熟悉且普遍的技术在此未被谈及到:

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

日常计划

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

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

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

你不需要学会所有的编程语言,你只需要专注在一种编程语言上。

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

  • 练习,练习,练习,直至我厌倦它,并正确无误地实现出来。(若有部分边缘条件没想到时,我会用书写的形式记录下来并去记忆)
  • 在纯原生的条件下工作(不需垃圾回收机制的帮助下,手动分配/释放内存(除了 Python))
  • 利用语言内建的数据类型,之后在实际工作的时候才能得心应手(在生产环境中,我不会去实现自己的链表)

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

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

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

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

必备知识

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

  • 并不需要实现
  • 这里有很多视频,看到你真正了解它为止。你随时可以回来复习。
  • 如果这些课程太过数学的话,你可以去看看最下面离散数学的视频,它能让你更了解这些数学背后的来源以及原理。

数据结构

更多的知识

树(Trees)

排序(Sorting)

  • 关于堆排序,请查看前文堆的数据结构部分。堆排序很强大,不过是非稳定排序。

总结一下,这是15种排序算法的可视化表示。如果你需要有关此主题的更多详细信息,请参阅“一些主题的额外内容”中的“排序”部分。

图(Graphs)

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

  • 笔记:

    • 有4种基本方式在内存里表示一个图:
      • 对象和指针
      • 邻接矩阵
      • 邻接表
      • 邻接图
    • 熟悉以上每一种图的表示法,并了解各自的优缺点
    • 广度优先搜索和深度优先搜索:知道它们的计算复杂度和设计上的权衡以及如何用代码实现它们
    • 遇到一个问题时,首先尝试基于图的解决方案,如果没有再去尝试其他的。
  • MIT(视频):

  • 完整的 Coursera 课程:

  • 我会实现:

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

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

更多知识

如果你需要有关此主题的更多详细信息,请参阅“一些主题的额外内容”中的“字符串匹配”部分。

系统设计、可伸缩性、数据处理

如果你已经拥有了4年以上的编程经验,那你可以来看看有关系统设计的问题

  • 系统设计以及可伸缩性,要把软硬件的伸缩性设计的足够好有很多的东西要考虑,所以这是个包含非常多内容和资源的大主题。要花费相当多的时间在这个主题上。
  • 考量:
    • 伸缩性
      • 把大数据集提取为单一值
      • 大数据集转换
      • 处理大量的数据集
    • 系统
      • 功能集
      • 接口
      • 类层次结构
      • 在特定的约束下设计系统
      • 轻量和健壮性
      • 权衡和折衷
      • 性能分析和优化