首先,面试者必须要自信,要能够像同事讨论一样面对问题,不能用考生对老师的态度,不要假想对方总是出难题来考察你能不能解出来。
我在 Facebook 面了大概 200 人,都是面 coding。如果说面试者的本质是一个搜索算法,在指定搜索空间内寻找题目的解法,那面试官就是一个搜索算法评估算法,在指定时间内调用搜索算法然后评估其性能和适应能力。
面试者的工作相对容易理解。给你一道题目,也就是给你一个搜索空间和搜索目标,然后你就搜索去吧。一开始可能你搜索到一个非最优的有效解,例如说暴力解法;然后可能你搜索到一个次优解,例如说 O(n) 解法;最后你找到一个 O(log n) 解法,你认为是最优解了,但实际上没办法证明。然后面试官再给你一道题目,这个过程重复下去……
面试官的工作则要复杂一些。面试官是要评估你的搜索算法是否足够好。足够好的意思是,将来在工作上遇到各种问题,你都能在合理的时间内获得最优解或次优解。面试官最明显的资源限制是时间,他只有 45 分钟的时间来调用你这个搜索算法,然后就必须给出结论。如果让你来设计面试官算法,你会怎样做呢?
最简单粗暴的方法当然是把面试官设计为跟 OJ 一样,他内置很多组输入和输出,把输入提供给面试者,然后等待正确的输出,测算一下消耗的时间。不过问题是面试官只有 45 分钟,这样做显然是不够的,所以必须把面试官算法设计得再聪明一下。
例如说,面试官算法应该去估算面试者算法在面对某一类搜索问题时的时间复杂度,如果小数据输入就证明面试者算法是 O(n^2) 的话,大数据就不用试了,显然会超时的。对比到现实中来,有些面试题是设计为有多个小问题的,如果你做到第 n 个小问题时已经花了不少时间,第 n+1 个问题就会被直接 cut 掉,根本不会问你,因为明知道问下去很可能是浪费时间。
又例如说,面试官算法应该去跟踪面试者算法对搜索空间的遍历方式,如果确定这个搜索算法在特定的情况下会触发特定的 bug,导致某个分支该剪不剪然后在上面浪费大量时间,那面试官算法就应该主动把搜索空间上同类的分支全部剪掉,避免这个 bug 每次触发时都浪费时间。别忘记了面试官算法必须在有限时间内评估面试者算法的性能,已经被鉴定的 bug 就没必要重复鉴定。对比到现实中来,如果面试者总是想不起来 API 或者公式,那就没必要再浪费时间让他回想,之后他在需要用到新的 API 或公式就直接给他,默默记录下来他不熟悉 API 或公式就是了。
如果面试者算法在某种输入上表现出 O(a^n) 的性能怎么办?或者说跟踪其遍历,发现根本不是在靠近目标。这时候就应该直接终止当前任务,换一个不同类型的输入。因为某些面试者确实不擅长解答某些类型的题目,浪费时间给他继续思考下去是没有意义的,面试官只是在不停地验证面试者确实不能解决这类题目而已,所以必须换不同类型的题目继续观察。(当然,我们会避免打击面试者的信息,所以就算要换题我们也会等到你有点进展的阶段,然后说我们对这个结果很满意,然后再换个话题。)
很多学生不理解的就是,面试官是全程观察的,因为中国的考试制度从来没有提供这种经历。中国的大多数考试都跟 OJ 一样,你只要最终的结果是对的就可以了,没有人在乎过程是怎样的。但面试官在乎的其实不是最终的结果,而是你实际工作的方式。面试官想要预测的是,假若将来跟你一起工作的话,你这种工作方式的效率高不高。举个例子来说,有个程序 crash 了,有人从头开始调试,有人二分排查,尽管得出来的结果一样,但从习惯上来说当然后者更好。(当然还有人看一下 log 就能凭经验说出来估计是调用了某个有 bug 的 API,然后 grep 一下所有调用该 API 的代码就解决了,你不得不承认这种剪枝效率超高,这种经验很值钱。)
至于刷题,大家都明白这相当于打表嘛。作为面试者算法,我猜你只会用特定的输入,所以我提前算好所有这些输入的正确输出,你提供搜索空间我就直奔搜索目标去。这种行为其实看起来有点可疑,但也不能说你什么。很多时候轻微调整一下搜索空间,或者是调整一下对最优解的要求,打表就会失败,然后就能看到真实性能。
此外上面所说的都是基于面试官非常认真想要做好的情况。当然面试官也有忙的时候,有时候也会心情不好。如果面试官一边面试一边打开电脑忙自己的事情,你基本上就挂了一半了。面试官算法是要消耗 CPU 的,如果面试官自己不能 100% 专注于观察面试者,那显然该为你剪枝的时候没有剪,让你重复犯同类型错误,没有主动寻找能够展现你优势的场景,结果通常对你不利。
【版权归作者所有,程序员大咖整理发布】
↙点击“阅读原文”,加入
『程序员共读』