程序员如何准备面试中的算法
春招季来临,大家陆续已经开始准备面试斩获心仪 offer。
这次 lucifer 就从面试官角度给大家分享一些面试技巧,让大家面试时少走弯路。这次分享侧重「算法面试」。
我负责公司的面试已经有 5 年以上了,基本都是初面和二面,因此技术面试的层面比较深,更多的是了解候选人的技术能力是否达标。在这几年时间,我前前后后也面试了很多的候选人。这些人中有的技术能力不行,但也有些人很可惜,技术能力是可以的,但是却没能通过我的面试,为什么呢?
面试考察什么?
首先,通常判断候选人是否可以通过面试有如下几个标准:
- 技能能否胜任
- 沟通能力如何
- 工作热情如何
。。。
那么我面试的时候肯定也是围绕上面展开的,只不过侧重考察不同罢了。
算法题和编程题实际上能够很好地检验以上信息,而不仅仅是检验「能力是否胜任」。前提是面试官不能太死板,比如直接扔一个网上原题,有的甚至自己都不太会就拿出来考,这肯定是不行的。
有同学反馈算法题目做出来了,但是却挂了面试。这又是为什么呢?
除了想当然的那种做的很好,实际上 corner case 没考虑到或者不是最优解。还是有可能会被挂,为什么呢?
其实你题目做的很好,仅仅可以证明「能力可以胜任」,这不意味着其他也满足要求,比如上面提到的沟通能力,工作热情等等。
那么如何更好地展示自己,给面试官留下更好的印象从而通过面试呢?除了提高自己的技术实力之外,方法也很重要。这里我就总结了几个技巧给大家。
算法面试基本步骤
- 我在网上找到一份《Interview Cheat Sheet》,这个 PDF 列举了面试的模板步骤,详细指示了如何一步步完成面试。
这个 pdf 开头就提到了好的代码三个标准:
- 可读性
- 时间复杂度
- 空间复杂度
这写的太好了。
紧接着,列举了 15 算法面试的步骤。比如步骤一:当面试官提问完后,你需要先下来关键点(之后再下面写注释和代码) 看完我的感受就是,面试只要按照这个来做,成功率蹭蹭提升。
pdf 地址[1]
- 多问几次,确保题目理解正确。
比如输入输出,corner case 等等。试想一个同事拿到需求不分青红皂白就去做,结果发现做出来的不对,多尴尬?你会想和这样的同事一起共事么?
比如你可以问:
- 需要考虑负数么?
- 结果的顺序重要么?
- 可以使用额外空间么?
- 。。。
- 先说思路,再写代码。
虽然题目理解没问题,但是可能思路根本不对,或者面试官不想要这个解法。
试想你是面试官, 对面写了半天代码。思路根本就不对或者不是你想要的解法,是不是有点失望?
所以尽量先说思路,面试官觉得没问题再写,「不要浪费彼此的时间」。
比如你可以说:
- 朴素的暴力的思路是:xxxx。而这么做的话时间复杂度是 xxxx。
- 朴素的暴力算法的瓶颈在于 xxx,我们可以使用 xxxx 算法进行优化,这样复杂度可以优化到 xxxx。
- 上一步骤给面试官讲思路的时候,代入几个例子。
corner case 和 normal case 都至少举一个来说明。这样不仅让面试官感觉你沟通能力强,而且可以帮助你进一步理解题目以及理清思路。
有点时候大家面试比较紧张,经过代入例子讲解紧张感会慢慢减少。就好像我做技术分享,往往紧张的就是前面几分钟,后面就不会有紧张的感觉了。
比如你可以说:
当输入为 [1,2,3,4] 时, 我们的先 xxxx, 这样就 xxxx,接下来计算出 xxxx ,最后 xxxx 。
当输入为负数时,我们可以直接返回 xxx。
- 写代码要快,不要来来回回改,不然就会被扣上 coding 不行的帽子。
其实有前面的铺垫,写快不难。因为前面其实讲思路,通过例子讲解法你已经对算法很了解了才对。
但是思路没问题不代表可以完整写出来。同样可以完整写出来不代表不需要涂涂改改。这需要大家做题目前先勾勒出代码的大体框架。
一个简单的技巧就是:「分模块写代码,一个功能一个函数」。这样可以减少不断地涂涂抹抹,修修补补的可能性。
一个例子:
def solve(nums):
def check(mid):
# do something
def another_func():
pass
# ...
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
check(mid)
其中 solve 为主体函数,而 check 和 another_func 则为拆分的函数。
- 写完代码自己先写个测试。
这不仅体现了你代码习惯好,而且能帮你发现代码写的有没问题。
小技巧:你可以把前面你和面试官举的例子以及面试官给的例子代进去看对不对,由于有前面铺垫了,这个应该也很快。
一个例子:
def solve(nums):
def check(mid):
# do something
def another_func():
pass
# ...
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
check(mid)
assert solve([1,2,3,4]) == True
assert solve([]) == False
# ...
这里我们使用 assert 进行了断言。类似于我们日常开发后对代码进行测试。
总结
最后给大家整理一个流程图,方便大家记忆,大家可以把图存起来备用。
最后希望大家可以在春招季斩获自己信息的 offer。也欢迎大家进我的春招群。加我微信,回复春招即可进群。
我的书 「《算法通关之路》」 已经出版了,想要突破算法面试的朋友不要错过,京东淘宝当当亚马逊等均有出售,电子版也有哦~
实体版购书链接[8]
电子版购书链接[9]
[8]
实体版购书链接:https://union-click.jd.com/jdc?e=&p=JF8BANYJK1olXQcDUV9VDUMeBF8IGloXVAIGU1pdCUIVCl9MRANLAjZbERscSkAJHTdNTwcKBlMdBgABFksWAm0BH18SWQYDXVxUFxJSXzI4UixRNl1GVjc-ci1CQA5RUl5sHVhZAlJROEonA24JG1MQWgMEUW5tCEwnQgEMGV4WVTYDZF5aCkMWA2kBH1sUVQ8yU15UOBBCbWgIHghBDgVQAw4JXx4nM18LK2slXTYBZBwzDUIWBWpdSVNFVFJQUQ1fDkMWAToKG1xCX1QEB1sJW0wnAW4JH1Il
[9]电子版购书链接:https://union-click.jd.com/jdc?e=&p=JF8BAL0JK1olXDYAVVhfD04UAl9MRANLAjZbERscSkAJHTdNTwcKBlMdBgABFkkWBW0PHlgUQl9HCANtcS0SdTFvWVt1X3BkVV4Kc0JxYRtPe1cZbQcyVF9cCEMSBGoOHmslXQEyHzBcOEonA2gKE1oVWwEKXV5cAXsQA2Y4QA57WgYHBwoOCxlAUztfTmslbQUyZG5dOEgnQQFaSQ5FWQYFB1cODhgSVDpaS1hFDwQLUlwJAU5DAWcJHWsXXAcGXW4
Reference
[1]pdf 地址: https://github.com/azl397985856/leetcode/blob/master/assets/cheatsheet.pdf