新手如何应对现场编程面试
我经常被问到关于现场编程面试的问题。和面试一样,现场编程面试的内容也千差万别。有些是完全开放式的,没有刁钻的问题,只是编写一些基本方法。有些是在像 repl.it 这样的实时协作环境中进行的。还有一些是标准的“这个字符串是回文吗?”之类的谜题。
这其中既有好消息也有坏消息。你不可能为所有事情都做好万全准备,所以没必要给自己太大压力。不过,即使你犯了错误,或者没能完成练习,你仍然可以遵循一些简单的指导原则,在现场编程时给人留下好印象。
虽然我个人因为畏惧而长期回避这个话题,但我还是尽力在下面的章节中列举了一些滑稽、易记且极其直白的例子,来解释大O符号。虽然这部分内容是可选的,但我希望你能尝试一下,也欢迎你的反馈👇
如果你还没准备好深入探讨大O概念,我会用以下指导原则来概括它(就编程面试中需要关注的可操作事项而言):
- 哈希数据结构是超级英雄(例如 Python 字典、JS 对象等)。
- 将需要循环的数据结构(例如数组)转换为可哈希数据结构会很有帮助。
- 将嵌套循环转换为单层循环也会对你有所帮助。
第一部分:入门
你正在参加面试。你可能知道也可能不知道面试中会有现场编程环节。在面试的前几分钟,我认为你有几个关键事项需要优先考虑:
花点时间安静地读一下题目📓
花一分钟时间阅读题目,然后再仔细琢磨一遍。先别急着想答案,确保你真正理解了。我以前也犯过阅读过快,草率地给出的答案忽略了一些边界情况的情况。
选择你最擅长的语言——认真点👨💻
如果可以选择编程语言,别担心选公司用的语言,也别为了“给人留下好印象”而选语言。面试本来就压力很大,选你最顺手的就好。如果不是他们用的语言,我以前会给出比较轻松的理由,比如“我刷 LeetCode 的时候大部分题目都是用 X 语言做的,所以就选它吧”。既然他们提供了选项,就说明他们打算让员工使用。别担心选 JavaScript 而不是 Ruby 会显得自己很差劲什么的。
确保他们的代码环境运行正常(运行“Hello World”程序) 👋🏽
信不信由你,我的协作工具居然出故障了!运行一个简单的日志语句就能检查一切是否正常。
与面试官沟通,为叙述和对话定下基调🗣️
让面试官知道你打算征求他们的反馈意见,并像在现实工作中与同事交流一样,与他们探讨你的面试方法。这样一来一往的互动会让公开演讲的感觉大大降低。
让面试官参与一些测试用例的编写🏁
在紧张的时刻很容易忽略一些事情,所以这是一个需要更多人帮忙观察的好地方。
综合以上几点,这和我通常在编程挑战面试开始时说的话很接近:
我:好的,那我先花点时间
自己仔细读一遍题目,可以吗?面试官:当然可以!请便。
...
我:太好了,在深入研究之前,我想先
在这个函数里快速运行一个“Hello World”程序,确保一切正常。
……
棒极了,看起来不错。我:那么现在开始吧,我会一边编写代码一边向你们解释我的思路和操作步骤。你们可以随时参与,我觉得这种协作方式很棒,也能让我们了解
如果我加入团队后,我们会如何合作。过程中我可能也会问你们一些问题。面试官:好的,听起来不错!我会不时提醒大家时间还剩多少,这样如果时间不够,我们还有时间讨论你下一步的计划。
我:好的,听起来很完美。首先,我不想遗漏任何极端情况。我打算编写一些测试用例,并判断它们应该通过还是失败。如果我在编写过程中遗漏了什么,请随时告诉
我。编程面试有时会让人紧张,我不想不小心遗漏任何东西。
(等等)
如果你问十个人他们喜欢如何开始编程挑战,你可能会得到十个不同的答案。有些人可能不喜欢我最后那句话,那就是我承认自己临场发挥可能会有所疏漏。但就我的经验而言,面试官对此的反应相当人性化,我甚至觉得这很有帮助。有时他们会提供我没想到的测试用例,有时他们确实能指出我尚未意识到的编程挑战的某些方面,而这些方面如果放在后面处理,我会浪费很多时间。
尤其是在你初次面对编程挑战,并且格外紧张的时候,你可能会沉默片刻,思考自己的解题思路,而这几秒钟却可能变成几分钟,你只能默默地坐在那里,焦虑不安。尽早建立起对话的融洽关系非常重要。对于初级程序员来说,在编程挑战的某个环节遇到困难其实很正常,但如果你已经和面试官建立了良好的对话节奏,那么说“我有点纠结,但我认为我的解题思路应该是这样的……”就容易得多,这样就能更容易地获得反馈和指导。如果你已经沉默了好几分钟,突然开口求助就会显得非常尴尬。
情况因地而异,但在很多面试中,代码是否能运行绝对不是他们唯一关注的指标。他们还会考察你的协作能力(尤其是对于初级员工!),他们会观察你如何应对模糊不清的情况,是否会主动寻求帮助,以及是否会陷入困境并最终惊慌失措。我认为,在编程挑战中,即使你的代码实现并不成功,只要你能清晰地表达出你的意图,就能获得一定的分数。
第二部分:身处风暴中心
所以你已经编写好了测试用例,代码也运行起来了。最后一步的那些琐碎的准备工作和收尾工作,在我做代码挑战的时候算是“轻松的部分”,而当你完成所有这些工作,只是盯着代码看的时候,就很容易失去理智。
💡以下列出的是执行主要任务时最重要的几项优先事项。
立即用注释的方式写出解决方案的步骤/阶段(“注释框架”) 🦴
对我来说,在编程挑战的早期阶段,情况大概是这样的:
// previously empty function where I did my hello world
function myCoolAlgo(sortedList, target) {
// first, I'm going to build a hash from my list items so that I can look
// them up more efficiently
// next, I want to build a separate validation method to check <blah>
// third, I want to <blahblahblah>
// next, I'll take the result indices and see if they are a prime number
// last, I'll return the result * 23
}
顺便说一句,注释内容完全是虚构的,我也不知道这会是什么样的代码挑战。但这跟我会写的代码风格差不多。
我喜欢提前注释掉我认为需要做的步骤。A)为了获得反馈,B)这样即使我慌乱中思路中断,也能有所提醒。对于可能保存代码的地方,这也能提供一些线索,让你了解如果时间更充裕,你的计划会是什么样的。
许多地方比你想象的更能理解你无法完成挑战。而有些地方,他们会列出一长串可以无限期增加的挑战项目,所以根本没有真正的“终点”。但你或许可以通过留下评论和想法,对那些你没时间完成的部分产生影响。
给代码添加“注释框架”或许是我在编程挑战中最有帮助的习惯之一。我是认真的,注释真的很有用。首先,它能防止你思路中断。看到新手程序员给他们的代码添加注释也很棒,因为初级软件工程师的代码本来就不够清晰,而注释对于职业生涯初期的开发人员来说尤为重要。我知道,如果面试者有良好的注释习惯,对我来说绝对是加分项。
说说你做出决定的原因和方式📰
如果你读过前面链接的关于大O表示法的文章,或者你的解决方案是基于性能方面的考虑,那么现在正是讨论你性能思路的好时机(即使你最终没有完全实现所有功能,也能获得部分分数)。这也是一个机会,让你在编写代码之外,以更直观的方式展现你的知识。
对于每个新增代码,运行一些测试用例🧪
如果你已经像我建议的那样,将代码注释成“章节”,那么在每个章节完成后,最好运行一些测试用例并记录运行结果,这样可以确保你不会继续在无法正常工作的代码上进行操作。
继续对话,征求反馈意见💬
保持对话在这里真的非常非常重要!即使你懂一些知识但没有付诸实践,你也真的可以获得“部分分数”。我知道我以前说过这样的话:
- 我感觉这方面性能还可以提升,我想先把这个功能搞定,等时间允许的时候再回头处理这个问题。
- 不知为何,我总觉得目前可能存在一些极端情况会给我们带来麻烦,但我说不出具体是哪一种……你有什么想法吗?
- 我原本希望为了提高性能能把这段代码简化成一个循环,但现在看来似乎只能增加一个循环了。如果最后有时间,我肯定会回来仔细优化一下,就像提交 PR 之前处理实际代码一样。
我有时在这些问题上会想,或者说,我心里想的是“YOLO(You Only Live Once,你只活一次)代码面试压力山大”。我觉得坦诚面对这个问题反而能让我放松一些。你知道吗,我时间有限,有些内容让我感觉不太对劲,我想再仔细看看,但考虑到时间限制,我还是先说到这里吧。
还有一些其他需要注意的事项🧠
- Ctrl + F 是个好帮手,记不住变量名可能是我在代码挑战中出错/调试的最大原因🥴 通常你可以用 Ctrl + F 向下搜索页面来追踪某个东西,至少可以排除这个可能性。
- 如果要在较长、描述性的名称和较短、含义模糊的名称之间犹豫不决,那就选择较长的那个。
- 即使时间紧迫,也要花时间确保代码格式合理,变量命名恰当。
- 虽然代码挑战通常只涉及单个函数,但如果你的函数过大,最好还是说明一下,或者干脆把逻辑拆分成一个单独的函数,以表明你理解关注点分离原则。如果时间紧迫,也可以在注释中简单地写上“通常我会把这部分代码拆分出来”等等。
- 有时候意外真的会发生!我们的协作工具就突然崩溃过。所以事先准备个备用方案总是没错的。我记得当时我建议我们换用repl.it和屏幕共享,结果我居然真的得到了这份工作,哈哈。
第三部分:总结
我觉得我做过的每一个编程挑战都是一次独特的冒险。第一次简直是一场灾难,之后我有好长一段时间都避而远之。我当时完全沉浸在代码里,最后写出来的全是胡言乱语。有些挑战我觉得自己表现平平,却意外地收到了工作邀请。还有一些挑战,我觉得自己发挥得淋漓尽致,却被拒之门外。
代码挑战其实是一种很糟糕的评估程序员的方式,因为公开演讲是人们最常见的恐惧症之一,即使没有这种恐惧症,人们仍然会对公开演讲产生很多其他合理的焦虑。
虽然现场编程挑战总是让人感到压力很大,但我认为真正糟糕的现场编程挑战屈指可数:
- 我问他们该如何准备,他们只字未提现场编程,结果在我们还没来得及闲聊之前就突然抛给我。我当时完全懵了(这就是我之前提到的第一个问题)。我记不清JavaScript 里
slice`and`splice和 `or` 的区别,然后就彻底崩溃了。当时感觉糟透了,但很快我就觉得这事儿有点搞笑。到最后,我知道自己搞砸了,就随便说说数据库方面的一些高见,因为反正也没什么大不了的。 - 他们用的那种代码编辑器根本没法运行代码。我以后可能都不会再用这种编辑器面试了。太不现实了!我们根本不是这么写代码的,而且说实话,它真的让我很崩溃,我觉得我因为这个前提条件表现得非常糟糕。
随着时间的推移,我甚至开始喜欢上编程挑战,因为它们相对来说比较快,很快就能完成。我做的越多,就越意识到,只要你积极沟通,即使没有完成,也能获得所谓的“部分分数”。我意识到,大家并不是像我之前担心的那样,只盯着我看有没有低级错误。这其实更考验你的思考方式和协作能力,而且我参与过的很多项目似乎都把按时完成当成了次要的。
但在你即将完成代码挑战之际,我还有最后几点建议给你:
- 重申一下你会在当前代码中更改/继续改进的任何内容(这里值得一提的是,你当然会为你编写的任何功能添加测试)。
- 感谢面试官抽出时间,并强调你相信自己完全能够在协作式编程环境中取得成功。
- 你可以简要地解释或承认任何出错的地方,以及事情发生的原因和经过,并说明你从中吸取了什么教训,或者将来如何避免类似情况再次发生。但一定要注意措辞,保持积极和简洁。
瞧,就是这样!
之后,您可以选择发送一封后续邮件。您可以这样补充说明:“我感觉自己很傻,当时竟然没想到这一点,可能是面试太紧张了。面试结束后我立刻意识到,我可以用 x 来做 y。真希望在面试过程中就能想到这一点。感谢这次机会,期待接下来的合作。” 如果您觉得面试时没有时间提及此事,那么在邮件中添加一些补充说明并不会造成什么负面影响,反而能展现您的自知之明。
结论
关于现场编程面试,我最想告诉大家的一点是:你不可能完美地准备。即使我已经做了很久,也还是会有发挥失常的时候。最近几次面试,不知什么原因,我前一天晚上都彻夜难眠。更糟糕的是,上一轮面试我竟然两次都这样!感觉两次都搞砸了,一次拿到了offer,另一次却被拒了。
实时编程本身就压力很大。对我来说,随着时间的推移,这种情况已经变得容易多了,所以练习或许真的有用。你完全可以和朋友一起练习,比如轮流做 LeetCode 题,同时通过 Zoom 或其他视频会议软件共享屏幕。
到了我人生的这个阶段,我不知道自己是否还能克服对实时编码的紧张,但现在它更像是去看牙医或其他一些平常的事情,而不是我曾经认为的可怕的挑战。
所以说到底,别灰心,这的确不是世界上最容易的事,但经验很有帮助。而且你永远不知道什么时候会走运。我曾经现场解过一道题,题目是我最近在 LeetCode 上遇到的一模一样的,而且我已经准备好了完美的解决方案。
实时编程总会存在一种令人不快的可能性,那就是让你感觉自己像个傻瓜,甚至蠢得要命,持续一个小时。但这些年来,我开始这样看待它:“我愿意为了加薪五万美元而忍受一个小时的愚蠢吗?”因为不止一次,这笔钱都岌岌可危,而实时编程最终帮我保住了它。所以,到了我这个年纪,我会说,管他呢,让我体验一个小时的愚蠢吧,最坏又能怎样呢😎
文章来源:https://dev.to/heyjtk/surviving-live-code-interviews-for-newbies-5hn6