本文作者最近在 interviewing.io(IIO)上完成了第 600 次面试。之后,他想分享下在这个过程中所汲取到的经验教训,以及为什么以这样的方式进行面试,并阐明一些他在技术面试中遇到的常见问题。
本文最初发布于 interviewing.io 博客,由 InfoQ 中文站翻译并分享。
interviewing.io 的模拟面试
在 IIO 上进行面试时,我们按 4 分的标准给面试者打分。1 分表示他们做得非常糟糕,4 分表示他们在这方面做得非常好。通常,在面试开始的时候,每个人都有 3 分(满分 4 分),然后随着面试的进行而得分或丢分。
这个平台上的每一位面试官都会有各自的偏好。作为一名面试官,我更看重的是沟通和解决问题,这一点我将在下面指出。
技术熟练程度
对于技术,我的打分依据是求职者对所选语言的熟练程度、他们在编写特定风格的算法时是否有严重问题以及在编写过程中是否需要大量提示。
问题解决能力
在这一点上,我的打分依据是:求职者有能力将问题分解成小问题、提出解决小问题的策略以及在此过程中 debug 的能力。debug 时思考问题的能力与编写代码的能力同等重要。当问题发生时,他们是被难住了,还是能够自己找到根本原因?
沟通能力
面试官真的很想听到你的决策过程,这在 debug 时也非常重要。我倾向于雇佣那些能够很好地融入小型开发者团队或群体的人。考虑到这一点,协作和容易沟通是赢得我的认可的好方法。
我在面试中看到的常见问题
以下是我在面试中看到的最主要的问题,不只是在 IIO 上,很多人都会有类似的问题出现。我希望这些建议对你有帮助。
常见问题一:面试时过快地开始写代码
我在所有类型和级别的开发人员中都看到了这一点,但这个问题大多集中在拥有 2 到 5 年经验的“中级”开发人员中。当他们听到一个问题,只用 30 秒或更少的时间描述高级设计(high-level design),然后就迫不及待地开始编码。他们总感觉自己有时间限制,于是想赶快把事情做完。可能在他们看来,这是一场通往终点线的赛跑,第一个冲过终点线的人就是胜利者。
可真的是这样吗?当然不。
请慢下来,好好计划一下,并在此过程中分享你的想法。
那些花时间思考中级设计(mid-level design)的人,不管是通过伪代码还是只写下他们计划采用方法的注意事项,之后 debug 时花的时间往往都更少。那些直接开始编码的人会陷入我所说的“边做边设计”问题,在这种情况下,你会花费大量的时间重构代码,因为你需要更改传递的参数或返回值,或者突然发现,循环的位置错了,等等。作为面试官,很容易发现这一点。
在中级设计上花一些时间并不能保证你获得成功,但是从长远来看,你可以通过对计划的更深入思考来节省时间,而额外节省下来的时间稍后可以用来解决问题。
另外,作为面试官,我希望看到你成功。特别是,当你在“现场”的时候,因为现场面试会让我们公司花更多的钱。虽然对于所有的求职者,我需要公平地给予帮助,但如果我能提前看到你的设计,并发现设计中的缺陷,我就可以问一些引导性问题来帮助你发现问题并提前纠正你的方法。
如果你直接写代码,我甚至不知道你的实现是否能工作,将面试官置于这样的境地可不好。如果在我真正理解代码中发生了什么之前,你就已经编写了 100 行 Java 代码,那么对我而言,要纠正设计就会困难许多。
在 2012 年的一场面试中,我看到了缺乏计划的可怕后果。人力资源部的人把求职者带到我的面试室,问他们是否需要喝水,并答应一会回来。我们互相做了自我介绍,然后开始了技术挑战。求职者们没有分享任何细节,没有任何设计,而且很少谈论上层的方法,也没有写下任何设计或思路相关东西,就开始在白板上写代码。(这将是我进行的倒数第二场白板面试,我讨厌白板面试!)几分钟后,HR 出现了,他敲门进来,送完水就离开了。求职者们很感激,纷纷打开瓶盖喝水,这时,他们的脸上出现了一种可怕的、精疲力竭的表情。送水分散了他们的注意力,这让他们完全失去了思路,我无法帮助他们恢复过来,因为他们没有跟我分享任何关于其方法的细节。他们花了几分钟重新思考这个问题,然后重新开始。
然而,另一方面,你可能在设计阶段花得时间太长,以致没有时间来实现你的“天才计划”。我曾经见过一些求职者讨论一个中级设计,他们做笔记,然后对照这些笔记手工进行示例预演,以确保他们的计划是一个好计划,可是他们只有几分钟的时间来真正地完成编程工作了。沟通可以得到额外的分数,但我们也需要看到一些可以工作的代码。
那么,最好的方法是什么?
通常,我建议你花 5 分钟思考高级设计,5 分钟计划和证明中级设计,然后再开始编写代码。好消息是“实践会让你变得更好”——你实践设计分解和解决问题的次数越多,你就会变得越好。关于这一点,稍后我将更详细地介绍。
常见问题二:不会沟通“不成熟的想法(Half-thoughts)”
这是我多年来创造的一个说法,你开始大声说出一个想法,完成你头脑中的想法,然后修改代码。情况通常是这样的:
“嗯,我想知道我能不能……不,没关系,我就这么做吧。”
让我们继续谈下我对沟通的偏爱。
面试官想知道你的思维过程。让他们知道你是如何做出决定的,这很重要。你是如何确定或否定你的想法的?为什么选择某种特定的方式实现某个东西?你是否发现了代码中的潜在问题?这个问题是什么?等等。
对你的面试官来说,这些缺失的信息是一个隐藏的宝藏。只需几秒钟,你就能把你的沟通方式变成这样:
“我想知道,是否……嗯……嗯,我在考虑将这个实现为深度优先搜索,但考虑到一个 ___ 存在约束,我想更好的方法可能是 ___,您认为呢?”
这可能会多花两三秒钟,你询问我的意见或寻求我的支持,我们可以一起考虑各种可能性,现在我们正在这个过程中进行合作。这种感觉仿佛你已经是我未来的同事了!
常见问题三:不做澄清式提问
在面试时,我经常会问这样一个用于热身的问题:
你有一组(a grouping)整数。编写一个方法,查找两个加起来等于给定目标值的数字,找到就立即停止,并报告这些数字。如果没有找到任何东西,则返回两个“null”值。
这是一个很好的问题,从中我可以看出,当你听到一个问题时,你如何思考算法和你所做的各种假设。
我从 1982 年开始就在从事编码工作了。在我使用过的语言中,没有哪一种提供名为“a grouping”的数据结构。关于这个问题,你会做什么假设呢?
大多数面试者立即假定一组(a grouping)数字就是一个数组。你可以使用一个数组来存储数字,成功地解决这个问题。你的算法可能是 O(n^2)(n 方)算法,因为你将以指数的方式迭代数据:对于每个值,遍历其余的值。通过选择不同的数据结构,有一种更有效的方法可以在 O(n) 时间内解决这个问题。
但其实,面试者可以询问面试官,了解有关这个提问的一些更详细的内容,如果他们让你做出不同的假设,则可以问一下他们你的假设好不好;或者问一下,是否有可能影响算法的替代数据集,你将使用它们作为测试用例。
常见问题四:以为所有规则都是面试官说了算
等等,什么?
对,你没听错。
是的,你是来面试的,但你是为了向他们展示你将如何在团队中开展工作,而当团队沟通明确开放、富有协作精神时,工作效果最好。在面试的前几分钟设定一些预期,特别是关于沟通和工作流程。
可以这样和面试官聊聊:
“对于这样一个技术挑战,我通常是花一两分钟静静地思考问题并记下笔记,一会儿我将与你分享这些想法并期待从你那里获得反馈。然后,当我编写代码时,我也倾向于安静地工作,但我肯定会不时地停下来分享我的思考过程,然后,在我们第一次运行代码之前,我会更彻底地向你介绍代码。你能接受吗?或者,你对我如何沟通或解决这个问题有什么不同的期望吗?”
我保证你会让他们大吃一惊。大多数面试官都不会准备好让你考虑他们的期望。这表明你能在团队中很好地工作,你在营造一种既为自己着想,又为他人着想的环境。你预先说明了自己的意图,并为他们提供了在这个过程中进行协作的机会。
常见问题五:不懂得尽早寻求帮助
作为你的面试官,我可能会在技术挑战中提供一些帮助。显然,我不能指导你完成所有的事情,但我会愿意给你一个提示,在一个规则上扣点分,然后看着你最终成功地解决这个问题,而不是默默挣扎,原地打转,让我们都觉得面试是在浪费时间。
作为一名专业面试官和软件学校讲师,我非常擅长问一些引导性的问题来引导你实现或者作出回答,而又不给出解决方案。
承认自己陷入困境是可以的,它不会让你成为失败者,因为人人都可能会这样。让你的面试官知道你在想什么,你的问题在哪里,仔细听他们的回答,他们可能会给你一些关于问题的提示,或者给你一些关于如何继续的更全面的建议。
建 议
当我们在 IIO 的面试结束时,我喜欢对他们的面试流程以及我认为他们可以通过实践进行改进的地方提出大量反馈。一般情况下,我会花 10 到 20 分钟来回答别人的问题,有时会超过一小时。我喜欢在 IIO 上帮助别人。
以下是我给大家的一些建议。
沟通
没有什么比听自己的录音更糟糕了。但是,所有的 IIO 面试都是录音的,我经常会在听完最后几分钟的录音并回顾我给他们的反馈后,在反馈和复审记录里告诉他们。你还可以随时暂停这些录音来获取一份代码副本。(这些录音当然只属于你和面试官。)
在回放过程中,倾听你自己的思维过程以及你是如何表达想法的。当你面对其他挑战时,如果可能的话,找个方法录下自己对这个问题的想法,然后回放给自己听。你会更善于完整而充分地表达自己。
问题解决和中级设计
HackerRank、CodeWars、LeetCode 等都是常见的进行算法编码练习的好网站,但却没有提供任何方法来练习设计过程。
我让学生去参加欧拉项目。欧拉是数学家,所以网站上的问题通常都很难懂,但你可以把问题改成你喜欢的形式。如果你不知道如何计算质数,没问题,你可以把它换成一个数是否能被 17 整除或者别的什么。
我喜欢欧拉项目,因为它的挑战都是应用题。你必须考虑所有的事情:算法、使用哪种数据结构,尤其是如何将问题分解成更小的部分。
我最喜欢的一个问题是他们存档中的第 19 条:计算 1901 年 1 月到 1999 年 12 月有多少个月是从星期天开始。他们告诉你每个日历月的天数,告诉你 1900 年 1 月 1 日是星期一,以及如何计算闰年。剩下的就看你了。
你接触的不同类型的问题越多,发现模式的能力就越高。
练习、练习、练习
我们给学生的一个建议是,每个技术挑战都要练习多次。我们的执行董事 Jeff Casimir 会让学生们把某件事练习 10 次。我的目标是 3 到 4 次,理由是:
当你第一次解决一个问题时,你所做的只是解决了这个问题。某些问题可能让你陷入了挣扎,而你唯一真正的成就仅仅是是把它完成了。
如果擦掉你的工作成果并重新开始,你可能会想到一个不同的方法来解决问题,也许是一个更有效的解决方案,也许不是,但至少你增加了关于这类问题的实践经验。
现在擦掉你的工作成果,再做第三次,然后是第四次。反复多次之后,你就会开始建立起用于解决这个特定问题所用策略的记忆。当你看到其他的技术挑战时,这种“肌肉记忆”将帮助你发现相似点。“哦,这看起来像我做过的某一类问题”,因为你已经解决过很多次了,所以进行高级设计和中级设计的时间会缩短很多。
我最喜欢的一种技术挑战是,通过不同的算法(DFS、BFS、DP 等)来解决问题。如果你认为自己可以用类似的方式解决一个问题,那么也可以用每种算法解决它 3 到 4 次。这样的话,你将非常擅长于发现相似点,并拥有一大堆处理其他技术问题的策略。
避免过度的自我推销
我一直在 https://techinterview.guide 上为有抱负的开发新人写备忘录。虽然还不完整,但我对技术面试、人际关系网及外联、简历和求职信等有很多自己的想法。关于谈判策略和优雅辞职,我还有几章要写,但我很乐意听取别人对这些内容的反馈。
我也有一个日常电子邮件系列,涵盖了几种面试问题,但不是从如何完美回答问题的角度,有很多资源可以做到这一点。相反,我从面试官的角度来审视问题——我真正想问的是什么、我希望你能告诉我什么、我希望你不会说什么,等等。举个小例子:当你被问到“谈谈你自己”时,他们并不是在问你的生活经历。他们实际上是在问“能否简要介绍下自己,证明自己可以成为一名有价值的员工”。
关于作者
William Ian Douglas 一直使用“Ian”这个名字。他住在科罗拉多州丹佛市,1996 年毕业于计算机工程专业。他的职业生涯涵盖后端系统、API 架构、DevOps/DBA 职责和安全,并曾担任过小型团队的负责人和工程总监。2014 年,Ian 涉足专业技术面试指导领域,并在 2017 年将他的整个职业生涯转向为丹佛区的图灵软件设计学院教授软件开发。2017 年夏天,他加入 interviewing.io 成为一名签约面试官,他非常喜欢 IIO 撰写的数据分析文章,这些文章帮助我们揭露和消除科技行业采访中的偏见。Ian 在 https://techinterview 网站撰写文章传播技术指导信息。你可以在 Twitter、LinkedIn 和 GitHub 上联系他。
查看英文原文:
评论