关于面试

155 阅读11分钟

背景

跳槽的缺点当然是为可怕的数据结构和算法面试过程做准备。

如何学习

我强烈建议积极学习计算机科学基础知识,以复习核心知识,以及常见的算法、数据结构和策略。

当我说“积极学习”时,我的过程是这样的:

  • 花一个小时左右阅读手头的主题——无论是递归、Djikstra、按位运算还是我那天想学的任何其他可怕的东西。

  • 做手写笔记。研究表明,手写笔记在记忆力方面要有效得多。

  • 把这个概念留一天。在此期间随意学习其他内容,但当您做其他事情时,让该主题最终出现在您大脑的分散部分。

  • 第二天,将这些笔记输入到知识库类型的程序中。

  • 大约一周后重新审视这些笔记——例如,如果主题是 HashMap 的实现——再次练习实现。

我的策略涉及多次重复访问/查看相同的信息。这是一种间隔重复的形式,也是让信息坚持下去的最有效方法之一。一次阅读信息是不够的。

我还建议在应对编码挑战时使用这种技术。例如,最初可能会在做涉及深度优先搜索的问题时遇到困难。此时可以查看答案,但几天后重新审视同一个问题并尝试回忆该技巧。再过几天,尝试使用该技术变体的类似问题。这应该有助于信息在你的大脑中“点击”,经过一些刻意练习后,你会发现自己最终相当擅长它。

有用的工具

之前我提到过使用知识库类型的程序——这些程序允许您在个人 wiki 中做笔记,显示概念之间的相互联系。我强烈推荐 Obsidian,它使用 markdown 文件,支持 LaTeX 格式、mermaid.js 样式的图形,并且具有极大的可扩展性,具有大量社区插件。对于那些好奇的人,我在这里开源了我的学习笔记——它绝不是完美的,但它让你了解了 Obsidian 的工作原理以及如何建立知识库。

还值得一提的是,写出编码部分时,不要使用 IDE。自动完成会给你一种虚假的安全感,而且你不会在面试中拥有它——我在 Sublime Text 中练习回忆算法和数据结构。

热身

Leetcode 最糟糕的事情之一是它很容易让你觉得自己很愚蠢,特别是如果你只是潜入其中,这会耗尽你所有的动力。两件事情:

  • 这意味着很难,并期待一些不适。你有时会挣扎,你必须克服这种感觉。我向你保证它会变得更好。

  • 如果你有时间,慢慢地爬起来会更容易也更愉快。通过热身问题做到这一点。

“热身问题”是超级简单的问题,可以让您进入事物的摇摆并以成功奖励您。我发现最有用的是转到 Leetcode 的“所有问题”集合,并按“最接受”(不是“难度”)排序,然后从那里开始。这真的有助于增强你的信心,让你觉得你可以开始处理更难的事情,我强烈推荐它。

我也强烈建议你在任何编码面试的早上做这些温和的热身问题。就像在体育锻炼前热身一样,这些会让你的大脑进入解决问题的模式,而不会让你陷入绝望的深渊,因为你选择以一个核心的动态编程问题开始你的面试日。

学习什么

缩小范围

“计算机科学”的范围相当大——我强烈建议尽可能缩小你的学习范围。有几个例子:

  • 在 X 公司,我知道他们不再问动态编程问题,所以我会跳过学习 DP 并专注于其他东西。

  • DP 问题非常罕见(即使经过大量练习也足够难),我愿意冒险并打赌我不会被问到 DP 问题。这样我就可以专注于其他事情并最大化我的机会。

对于任何一种方法,尽可能多地花时间在 Leetcode 论坛或 Blind 上,基于目标公司/公司尝试找出你可能被问到的问题,以及不太可能被问到的问题。然后适当地优化你的学习。在某些方面,这是一场冒险的赌博,但对我来说,缩小学习范围的好处是巨大的,因为它让我真正专注于更相关的事情。

可以做的另一件事是按公司搜索 Leetcode 问题,然后按频率排名。这也将大致了解应该关注的地方和避免什么。请注意,这是为了对主题有所了解,而不是为了找到可以记住的问题 - 这是愚蠢的差事。当问题出现在 Leetcode 上时,公司往往已经淘汰了它们。

数据结构

从里到外了解你的数据结构是很重要的,在你做任何其他事情之前,我建议你确保你知道最常见的那些。这包括插入/删除/查找的空间/时间复杂度——你会被问到这个——以及它们的实现。确保可以构建一个简单的 Map、Trie、Linked List 等并对它们进行常见操作。令人惊讶的是,只需在正确的位置插入适当的数据结构,就能解决很多面试问题。

学习模式

我发现的另一个高价值策略是学习许多面试问题中的常见模式以及何时应用它们。通过利用这些策略的 Leetcode 问题示例,总结其中的大多数问题。如果你练习了所有这些,你会做得很好 - 编码问题的大部分斗争都是制定方法,并且对此有启发式的帮助非常大。

盲人 75

绝对物超所值的方法是通过所谓的 Blind 75。这是一个问题列表,涵盖了可能在面试中看到的所有编程技术和算法.如果你时间紧迫,只有几周的学习时间——这些问题是你想要一遍又一遍地做的,以将它们内化。再次,如果可以的话,进一步缩小这些范围。

系统设计

你可能是一名移动工程师,但仍然会被问到系统设计类型的问题。不过,您究竟会被问到什么是一个悬而未决的问题,这不仅因公司而异,而且因团队而异。在 FAANGs,你更有可能被要求设计一个分布式系统而不是移动客户端,如果你像我一样,你在这方面的经验很少 - 所以专注于这一点,因为你可能会设计移动端不学习的建筑(尽管如果你有时间仍然学习它!)。

也就是说,这是一个连续统一体,您可能会被要求同时设计一个分布式系统、一个移动客户端或两者的交集——在这种情况下 API 是什么样的,以及后端设计决策的权衡导致前端?

或者更有可能他们不会具体说明,当面试官问“设计 Instagram”时,你可以确切地询问面试官的意思。如果我只能为系统设计面试提供一条建议,那就是“提问”。

开启信号

信号是你的面试官正在寻找的,它们表明你的资历水平。如果你的目标是更高的薪水,你会想要给出信号,让你可以考虑更大的图景——你正在编写的代码将适合更广泛的系统。能够讨论权衡也是一个很好的指标——你是否选择了较慢的写入而不是较快的读取?你为什么要为此优化?这在分布式系统中有何意义?

一般来说,系统设计面试是你思考这些问题的地方,也是赚大钱的地方,但如果你也能在面试的编码部分讨论这些事情,那就更好了。

公司热衷的另一个信号是领导能力——你带领一个项目或团队取得成功吗?如果你导致他们失败(它发生了!),你在这个过程中学到了什么?展示有利于公司的决策是很棒的;向同事展示指导技巧、个人成长和同理心也是如此。

你通常会在面试的行为部分这样做,很多人对此准备不足。花大量时间审视你在每个角色中取得的一切成就,你失败的一切,并找出你从经验中学到的东西,这是值得的。把它全部写下来,真正地反思它并内化它。我发现这样做真的很有趣,我将从这个过程中学到的关于自己的见解应用到其他工作中。

归根结底,我在这里想说的是,面试过程的某些部分比其他部分更重要——这取决于你优化的目标。编码部分应该被视为相当二进制 - 需要通过它才能获得报价。但是系统设计和行为部分是倾向于升级(耶!)或降级(嘘!)的地方,许多人忽略了它们。

一般提示

你不能足够地表达你的想法。大声解释每一个想法。这不是很自然,但你的面试官想知道你的想法在哪里。尽管感觉很奇怪,但完全可以在家中练习。至少做几个问题,像在面试官在场时一样自言自语——这会让时机成熟时感觉更自然。

使用空函数并稍后回填。很容易卡在一个小的实现细节上——但有时你可以有点手忙脚乱。例如,您可能希望调用一个函数,该函数对某些值做一些复杂的操作,作为更复杂算法中的子例程;给它一个适当的名称,将其留空并继续解决方案的整体实施。如果你幸运的话,你的大脑会在你做其他事情的同时在后台完成实现,最后你可以回去实现它。如果你真的很幸运,面试官可能不会关心这个微小的实现细节,你也不必这样做。

对公司进行研究。阅读他们的技术博客并提出问题,让您清楚地了解他们已经大规模解决的一些问题。这会给你带来严重的布朗尼积分,但无论如何你都应该这样做,因为你对他们的所作所为感兴趣。

在系统设计面试期间写下很多笔记。写一份清单,列出你知道你想要解决但尚未完成的事情,并将其写在面试官可以看到的文件上。这样他们就知道你正在考虑所有方面,即使你最后没有时间了。此列表可能包括:

可扩展性
安全
可访问性
可维护性
日志/分析/可见性
合规

当测试编码解决方案时,请逐步执行并在每一步的注释中实际写下每个变量的值。面试官更容易跟上,对你来说也更容易陷入困境。将在此步骤中发现错误 - 这就是测试的目的!但不要紧张。找到它并纠正它总比不注意要好。

资源

编码

Leetcode 是没有办法摆脱的。如前所述,Blind 75 可能是您希望从这篇文章中获得的最有用的资源,尤其是在时间有限的情况下。

系统设计

对于分布式系统的示例和“设计 WhatsApp”等常见问题,我发现 Grokking The System Design Interview 课程非常值得。答案不是非常深入,但这并不重要 - 它让您对如何回答这些类型的问题有一个广泛的了解。如果您是一名移动工程师并且以前没有做过类似的事情,那么这是一个非常有用的资源。

有些公司会问你以移动为中心的系统设计问题,为此我发现这个框架不可能有用。虽然我们的移动工程师一直在做系统设计,但如何回答这些问题有点神秘,而且那里的信息很少——除了这个优秀的 repo。