前面试官讲述如何顺利通过 Facebook 的编程面试?

阅读数:1861 2019 年 10 月 18 日 15:02

前面试官讲述如何顺利通过Facebook的编程面试?

去年,我在面试 Facebook 的工程师候选人这项工作上花费了无数时间。

无论是作为面试官还是求职者,既然我都有所经历,于是我想在此分享一下自己的经验。

也许你是一个应届毕业生正在寻找你的第一份软件工程实习,也许你已经是一名软件工程师最近想寻求跳槽到新公司的机会。

或者,你可能不属于上述任何一种类型,而是正试图从一个完全不同的行业进入软件工程的世界。

这篇文章展现了我在 Facebook 担任软件工程师面试官期间学到的最重要的经验。

编程面试的过程常常让很多人感到沮丧,我衷心希望这篇文章分享的经验能给大家带来一些启迪。

面试的形式

编程面试通常是 45 分钟的长谈,目的是考察求职者对数据结构和算法的知识。

一般而言,大多数公司要求实习生只需参加编程面试。然而,对于有经验的高级应聘者可能需要进行两到三次编程面试、一到两次系统设计面试以及一次针对个人行为的面试。

首先声明,这篇文章只涵盖针对编程面试的建议。

最近经常有人问我,“如果在面试中,我不能迅速得出问题的解决方案,我该怎么办呢?”

我的回答是:“嗯,如果这真是一个优秀的面试问题,你不知道怎么解决,这才是正常状况。”

如果问题的答案显而易见,那面试还有什么意义呢?编程面试的目的是迅速了解你的编码能力。在 Facebook,我们将之称为“信号”。

作为面试官,我们的目标是尽可能多地获取来自求职者的“信号”。这就意味着,如果我们一旦察觉你以前遇到过某个问题,我们就会换另外的问题来面试你。

因为,我们想知道你如何在逆境中处理难题。

如果你碰巧照本宣科地背出了一个你从“编程面试宝典”中看到的答案,那么在这场面试中,我们其实对你解决问题的真实能力一无所知。

编程面试的最佳范例

那些绝顶优秀的候选人会在面试中扮演主导角色。他们几乎不需要面试官的指导。他们是主导谈话的人,而不是面试官。

在面试官提示甚少或没有提示的情形下,这些应聘者通常就能主动地自行完成以下这些步骤:

  1. 提出问题以进行澄清。

  2. 分析各种解决方案并权衡多种方案。

  3. 使用伪代码规划解决方案。

  4. 实现解决方案。

  5. 对解决方案进行测试。

主导但勿急躁

主导面试并不意味着求职者一上来就匆忙地去编写代码。事实上,在面试开始的前五分钟就着急动手写代码,对于面试官来说通常是一个非常糟糕的信号。

一般优秀的面试,第一步是提出一些好的问题对面试题目进行澄清。

问一些好的澄清性问题

在你开始着手解决这个问题之前,你需要先弄清楚这个问题是什么。

问几个澄清性的问题对你迈向成功大有裨益。

以下是一些不错的澄清性问题的例子:

  • 这段程序会运行在指定位置吗?(即没有额外的内存)

  • 我们能对输入做任何假设吗?

  • 我们更关心性能还是更关心节省内存?

这能让你专注于那些关键要点,而对其余部分进行忽略。知道该忽略什么和知道该关注什么,往往同样重要。

不要想当然地做出假设

太多时候,候选人会对问题做出假设,例如,所有的整数都是正数的,数组不为空,所有的输入都是安全的,这样的做法真的很危险

永远不要假设所有问题的条件都是相同的,尤其不要因为这样的普适条件方便你解决问题,就轻易做出这样的假设。相反地,应该主动问:" 传递给这个问题的整数都是正数吗? "

就是这样简单明了地提出问题。如果面试官的答案是“是”,那很好,你不需要额外设置检查。如果答案是“不”,那么也只需加一个简单的 If 语句就可以保证代码的安全性。

通常,提出这些问题可以给你很多方向性的提示。

讨论多种方案之间的权衡

我们这些面试官尤其喜欢看到候选人主动讨论解决问题的各种方法。

这不仅表明你知道总是有多种方法可以解决同一问题,但更重要的是,这样能迫使面试官在你没有明确要求的情况下给你更多提示。多棒啊!

作为面试官我们当然不会轻易给出正确的答案,但如果你提出了两种解决方法,A 和 B,然后主动提问,“你们认为我应该采取哪种方法呢?” 这样的情况下,面试官当然会选出那个更接近自己理想答案的方法。

使用伪代码规划解决方案

通常,在这些编程面试中,你会使用白板进行现场编程。这意味着你不能像在电脑屏幕上便捷地在需要的地方插入语句。所以在编写代码之前,你必须想清楚自己要做什么。

先深呼吸一口,对你的代码做出初步规划。这种规划可以用伪代码的形式,也可以用简单的绘图,但是要确保,你明白自己将要使用什么样的数据结构以及需要跟踪的变量。

我敢肯定,你不希望自己写在白板上的最终解决方案和下图一样潦草混乱:

前面试官讲述如何顺利通过Facebook的编程面试?

实现你的解决方案

这是让每个人忐忑不安的一步,但真没有必要为此过度紧张。

实现你的解决方案应该是整个面试中比较简单容易的部分。因为在这之前,你已经提出了很好的澄清性问题,充分考虑了各种不同的解决方法,还为你的算法做出了规划;现在你唯一要做的就是按部就班地写出代码。

但是当你写代码的时候,千万别忘了……

和面试官保持沟通!

请大声地和面试官谈论你的思路。如果面试官不知道你在想什么,就很难帮你在这个过程中把握正确的方向。

如果在编程实现的过程中,你方向走错了,作为面试官我可以插话进行提示。如果你方向走对了,我很可能会让你继续下去。

一个小提示:当然面试官的个人风格可能也是一个影响因素。有些面试官在插话时比其他人更积极主动一些。

对解决方案进行测试

由于某些原因,这往往是最容易被忽略的一步。我想说,我面试过的候选人中有 98% 本可以因为把测试做得更好而提升面试成绩。

在面试开始的时候,面试官常常不仅会给候选人面试问题,还会给出一个测试用例样本。

当候选人写完他们的解决方案时,他们将运行之前给定的测试用例。但这里唯一的问题是什么呢?一般面试官只会给出最简单的测试用例。而这个测试用例往往不会是边界用例,也不足以对你的代码进行恰当的测试。

如果你的算法仅仅可以为这个简单测试用例提供正确的输出,这并不意味着它可以为每个用例提供正确的输出。

因此,在编码面试中脱颖而出的最简单方法就是——编写更多的测试,比如编写更难的测试,或者更综合性的测试。

通常,这将帮助你在不需要面试官介入的情况下就能自己发现 bug。这样当然会让你的面试表现更优异。

当你不知道该做什么的时候,应该怎么办?

那么,如果在面试中你遇到一个你不能迅速得出解决方案的问题,应该怎么办呢?

我还是建议你一步一步地来。

首先回想一下,看看这个问题是否让你想起了另一个以前曾遇到过的问题。在面试中我问的许多编程面试题都是基于大多数数据结构和算法课程中讲授的基本算法问题,稍加一些变形(即设置“题眼”)。

如果你实在什么都想不起来,也不要惊慌失措。这也完全属于正常情况。

不要一开始就试图找出最有效的解决方案,这会让你压力很大。不妨先从最简单的解决方案开始。

然后在此基础上,去思考这个简单方案的瓶颈在哪里?这个算法最低效的地方在哪里?你能做些什么来尽可能消除这些低效的部分呢?

用数据结构的优点去弥补解决方案的缺点

当试图提高算法的效率时,有时(虽然不总是)可以使用数据结构来获得帮助。

每种数据结构都有其优点和缺点。例如,哈希表的优势在于查找速度,BST(二叉搜索树)的优势在于排序,等等。

如果你能够利用特定数据结构的优点去解决问题的瓶颈,这时候往往就会出现一些解决问题的最佳方案。

例如题目:

给定一个句子,请返回字母表中每个字母出现的次数。

一个靠蛮力解决的方案是一次性地挨个数出每个字母出现的次数,然后再输出结果。这里的瓶颈在于存储 / 查询信息的效率。我们需要存储句子中每个字母出现的次数,并在在结束时查询最终结果。

如果我们回忆一下所有可用的数据结构,这时总会有一个数据结构脱颖而出:

  • 二叉搜索树
  • 数组
  • 哈希表
  • 平衡二叉树
  • 堆栈
  • 队列

对于这道题而言,能最有效地存储和检索数据的数据结构是哈希表。

所以,如果我们用一个哈希表来解决这个问题,就不需要遍历这个句子 26 次。我们只需要遍历一次足矣。

寻找“题眼”

通常,面试问题会有一个“题眼”,一旦找到这个点就可以让你更有效地解决问题。

题目中常常有一些微妙之处,形成了一个独特的条件,允许你做一些较之平常更有效率的事情。请务必擦亮眼睛去寻找这些微妙的点。

这里有一个例子:

给定两个已排序的整数数组 A 和 B,请将 B 并入 A 成为一个排序数组。

你可以假设数组 A 有足够的空间容纳来自 B 的更多元素。在 A 和 B 中初始化的元素数量分别为 m 和 n。

这是一个直接来源于“编码面试宝典”的问题。

但你注意到这里的“题眼”了吗?

面试官本可以直接这样给出问题:让我们合并两个已排序的数组。但这道题的叙述不是这样的。

这道题给定了两个数组,其中一个的空间可以完全容纳另一个。

这就是我所说的“题眼”。当你遇到这样的题目,请注意,这些微妙的条件存在是其有原因的。

这些预留的数组空槽,实际上为你提供了一个机会来更有效地解决这个问题。

你可以在这里阅读完整的解决方案。

寻求帮助

有时候,即使一步一步执行了之前所有这些步骤,你还是不知道何去何从。在这种情况下,你应该主动地寻求帮助。

毕竟沉默地站十分钟对面试双方都没有任何好处。如果你真的不知道该怎么下手,向面试官寻求一个提示是正确的做法。

每个人都时不时地需要一个提示。重点在于你会如何充分利用这个提示。

结束语

技术面试现在就像 ACT、SAT、GRE 等考试一样,已经是一种标准化的测试了。虽然面试问题的细节可能会有所区别,但用于解决这些问题的主要概念和策略都还是非常标准化的。

许多候选人在简单的事情上出了差错,结果搬起石头砸了自己的脚。比如,想当然地做出一些假设,不与面试官交流自己的想法,以及编写很糟糕的测试。

然而这些错误都是可以纠正的,并最终会决定一个候选人是否会被雇佣。

如果你遵循了我在这篇文章中所概述的面试框架,相信你一定会在编程面试中表现优异。

作者介绍:

Ish Baid,前 Facebook 工程师,在线课程直播网站“ Virtually ”的创始人,该网站让内容创造者们创建和扩展在线培训业务。

原文链接:

How To Ace the Coding Interview, by an Ex-Facebook Interviewer

评论

发布