技术面试中的手撕代码应该如何准备?
The following article is from 吴师兄学算法 Author 吴师兄
第一时间收到文章更新
已获得原公众号的授权转载
今天给大家分享一下技术面试中的手撕代码应该如何准备?。
不管是秋招还是社招,互联网大厂的技术面试中的手撕代码这一部分总是绕不过去的一关。不只是后端开发和算法岗,现在就连前端、运维、测试、数据等岗位也要考手撕代码了。
咱们从是什么、为什么、怎么做来分析这个问题。
手撕代码是什么
手撕代码其实是广大求职者的一种略带戏谑的叫法,指的是在技术面试过程中,面试官给候选人出一道题目(大部分情况下是算法题,少数情况会出SQL题),让候选人在规定的时间内将题目完成。
之所以叫做手撕,大概是因为在口罩事件之前,一些线下面试会让候选人在一张白纸上直接写出代码/伪代码,而不会直接在电脑上运行程序。
由于目前大部分的技术面试都在线上进行,手撕代码的形式也就变成了在IDE或者在线编译网站中完成代码。
为什么要考察手撕代码
很多同学对手撕代码叫苦不迭,工作又不是做题,为什么偏偏要在面试中考察这样一个看似和未来业务关联不大的内容呢?
如果你吐槽数据结构与算法在未来用不上,那难道项目、八股就用得上吗?难道面试官会不清楚这一点吗?
实际上,相比起笔试可以代考、项目可以编造、八股可以硬背,面试的手撕代码部分反而是最公平、最能考察候选人水平的方式。
考察候选人的coding能力。假设候选人笔试分数很高,但是面试的手撕写得磕磕绊绊,连一些最基础的语法都写不好,那显然前面的笔试就很有可能是作假的,自然也就不能通过面试。
考察候选人在短时间、高压下解决问题的能力。面试通常是非常紧张的,但如果在这种高压状态下也可以很好地完成任务,说明候选人能够胜任具有挑战性的、紧急性的工作。
考察候选人抽象的逻辑思维能力。算法题通常而言都比较抽象,能够较好地解决算法题的候选人,通常具有较好的逻辑思维。
考察候选人的阅读理解、提炼信息能力。除了LeetCode上常规的经典题以外,现在也慢慢出现了一些题干较长、描述较复杂的题目,这需要候选人沉下心提炼关键信息,把已有信息转化为简单问题,再转换为代码语言。
考察候选人的沟通交流、语言表达能力。这一点其实很多人会忽视。在做完手撕代码后,一般都需要向面试官讲解你的思路和代码,如果能把一个相对复杂的算法(比如dp)讲清楚,那么说明候选人语言表达能力是过关的,在未来也能够胜任团队协作的工作。
考察候选人是否具有持之以恒、坚持不懈的学习决心。算法学习非一日之功,一般来说都需要经过1-2个月的系统学习和刷题。能够把常见算法学好的同学,说明都是有毅力有决心之人。
另外,从用人单位降本增效的角度来看,与其让更多的面试官花时间经历深挖简历,还不如一场算法笔试、一次手撕代码对人才的筛选力度大,这对企业来说是更加节约成本的招聘方式。
如何准备手撕代码
手撕代码和笔试是可以一起准备的,因为本质上考察的都是数据结构与算法知识。
算法题的考察实际上是一种半标准化考试:虽然没有考试大纲,但常考的知识点就是那些,题目通常以变换题干或结合不同知识点的方式来考察候选人能力。
各个知识点的难度可以大致用以下表格划分
难度 | 知识点 |
---|---|
入门 | 数组、字符串、链表、排序 |
简单 | 栈、队列、哈希表、双指针、贪心 |
中等 | 二叉树、堆、单调栈、滑窗、二分、位运算 |
困难 | DP、DFS、BFS、回溯、并查集、前缀树 |
上述表格只是一个非常粗糙的划分,需要循序渐进地进行准备和刷题。如果暂时无法自己想到解题思路,则可以先看答案,模仿他人代码,过段时间(比如一周)之后再重新尝试自己实现代码。
如果时间充裕且自我总结的能力强,那么完全可以自学网上的免费内容(比如代码随想录等),注意刷题过程中要做好每一个知识点的归纳。
如果时间紧张或者缺乏自驱力,那么找一个靠谱的算法老师或者参加算法培训,让有经验的人带着你一起学习,能够会得到事半功倍的效果。
另外,手撕代码和秋招笔试最大的不同在于讲这个动作。所以还得有意识地培养自己逐行讲解代码,讲解思路的能力。
这个其实有点像费曼学习法的过程:如果你能够把一道题目给其他人讲懂,那么说明你自己一定是真正学会了。
手撕代码注意事项
假设你已经把算法学得相对透彻,那么在技术面试的具体过程中,我们在一场手撕代码中向面试官展示出自己的水平呢?
仔细读题。把题目理解正确毋庸置疑是非常重要的。有一些描述的细微区别,比如数字范围是整数/正整数,子序列是连续/不连续,字符串包含/不包含数字,数组已排序/不排序等等,都有可能影响整个题目的代码,甚至使用完全不同的算法。尤其在遇到题干费解的题目时,在正式作答之前一定要向面试官再三确认题目是否理解正确。
做好注释。这不是说在写代码的过程中一定要加上注释,而是为了保证后续的讲解能够更加流畅,可以在适当的位置加上一些简单注释。比如dp问题,那么可以加上dp数组的含义、动态转移方程、dp数组的初始化这三个关键点相关的注释,这既是写给面试官看,也是写给自己看的。当然,如果你的能力强到可以一边写一遍讲解代码,那是最好不过的了。另外,也要尽可能地也保持良好的代码规范,比如
" = "
前后加上空格,变量名命名清晰等等。条理清晰。完成题目之后,面试官通常而言会要求你讲解代码或者算法,那么我们可以使用总-分-总的形式来进行讲解。
总:代码用了什么算法?为什么可以使用这种算法?时间复杂度和空间复杂度分别是多少? 分:按行或按代码块来解释代码。关键的变量在哪个位置发生了变化?用到哪些API?程序在运行过程中是如何一步步得到答案的? 总(这一点不是必须的):除了代码所示的算法(比如用了DFS),还有哪些可能的算法(那么BFS可能也是可以做的)?其优缺点是什么? 虚心请教。如果题目写不出来,或者完全没有思路,可以向面试官求助,虚心请教本题思路是什么?有什么建议?一般而言面试官都会给你一些点拨。如果在提示下能够较好地完成题目、写出正确的代码,也会给面试官留下不错的印象。
另外,手撕代码和笔试略有不同的地方在于,更大概率会考察经典题,主要以LeetCode中的简单题和中等题为主,而且考察种子题的概率更大。所以一定要多加练习经典题型。