- 本文作者:易潇
- 她的 Github:https://github.com/lilyzhaoyilu
大家好,我是易潇,也是 91 算法群里大家熟悉的狗头。最近申请和面试基本结束,刚刚过了Google 的 HC。
我的本科读的是商学,所以算是文科转码
和0基础转码
的一员。在这里想跟大家分享一下我面对面试刷题的心得~
注:Google 的招人模式比较特别,过了 HC 可以视为被 Google 接受并且已经结束了所有技术性面试,简称过了。具体关于申请 Google 的信息会在后续的文章中跟大家分享,敬请期待。
我的刷题情况
在谷歌面试的时候,我大概刷了 550 道题左右:其中大概 150 道简单,310 道中等,90 道困难。其中有中国站一些剑指和面试经典的重复题。对于前 200 和一些高频题,我刷了两遍以上或者更多。
如上图是我刷图论的模板题。左侧是我的提交记录,右侧是我的代码。
我在四月份之前断断续续的大概刷过 60 道题左右,然后在四月份的时候我新开了一个进程并且开始好好刷题。完成最后一个面试是 7 月 20 日。
刷题心得
按照一个基于 tag/topic 的计划开始刷题
tag/topic 的定义:在力扣题库界面的上方可以看到不同的标签(tag),点进去就可以进入每个标签的列表。
按照标签刷题的好处是它能帮助你巩固你对某个数据结构的理解,并且不断的改正和进步。
网上有很多大佬分享过刷题顺序和题单,或者你也可以自己创建一个列表。我觉得不用太纠结“到底哪个列表最好”,作为一个刚开始刷题的人,今天先学 A 或者 B 一般来说影响不会太大 —- 反正到最后都是要学的。最重要的是“开始学”,不要害怕计划不完美。计划肯定不会是完美的,是会随着自己的认知和进度而修正的。
对于我个人来说,我幸运的参加了力扣加加举办的 91 天算法。91 算法要求每天一起打卡一道题,并且每个礼拜的题都是围绕一个数据结构。这样按照一个标签集中刷题很好的验证自己对某个数据结构的知识并且修正了自己一些错误的认知。
建立一个有正向反馈的 Todo List
为什么我这么推荐按照计划刷题呢,还有一个原因是 Todo List 是一个很方便建立正向反馈的工具。为什么建立正向反馈很重要呢 —- 你如果打过游戏,那么你一定有过“呀就打了一会儿游戏怎么就这么点啦”的感觉。打游戏的时候时间过的飞快就是因为大多数设计好的游戏都会不断的给予玩家正向反馈。同理,我们想要一直刷题,那么就要给自己创造一个有持续正向反馈的环境。
Todo List 就是这样一个工具。我刷题的时候使用的是ipad + goodnotes + ElenaLin_青青的电子手账模板 + apple pencil。一般来说,我每天会制定第二天需要做什么事情,并且尽量把它拆分成小的、容易完成的步骤。比如说我想学习字典树,那么我就会把计划拆分成:
- 看 91 算法的字典树专题
- 写 91 算法的字典树模板题 LC208
- 写 91 算法的字典树推荐题
- LC211
- LC212
- LC472
- LC648
- LC820
- LC1032
- (如果还有精力)做力扣上字典树标签里的高频 5 道题
一般来说,除了学习某个专题,我的一天还会有一些其他事情,比如打卡 91 算法每日一题,打卡力扣每日一题,看邮件,投递申请等等。大部分时候,我起床之后坐在电脑前,都本能的觉得“太难了”,以至于“我不想干”。每当我有这种感觉的时候,我就在所有的待办事项中选一个我觉得最容易完成的项目并且开始做。换句话说 —- 别想那么多,兄弟,冲就完了!(好吧我是个 fps 游戏玩家)。我一般会选择先做 91 每日一题,因为它不会太难,而且打卡了之后会被其他刷题小伙伴看到,这让我有种觉得自己很棒棒的感觉。只要开始建立 “克服困难” -> “执行任务” -> “完成之后感觉自己很棒棒” 的行为模式之后,一切都会变得简单起来。
ElenaLin 的电子手账使用教程可参考这个视频 https://www.bilibili.com/video/BV1Ai4y1w7ZM
贴一个我中期的日程表,这个时候我已经建立了比较好的循环,所以会看到每天完成的任务多了起来,而且我也已经不太依赖“在完成每个任务之后划掉”这个动作了。我的笔记也并没有很整洁或者美观,只要自己能看懂就可以。
当然,在工具上不一定要跟我一样。本子和笔也可以。不过我强烈推荐用一个本子,因为周末和月末的时候回顾看看也会继续加深上面提到的有正向反馈的行为模式。
学会站在巨人的肩膀上
一道题看10 分钟如果没有思路就不要太浪费时间在错误的方法上面,学会看和学习别人的题解。
一般力扣解题区的高票题解都很好。一个题解如果看不懂也没关系,首先照着它写一遍,然后通过各种打印和调试搞清楚每一行代码都是在做什么;如果还是不清楚为什么,可以把某一段代码注释掉再点提交。这个时候系统会报错,你再拿着这个输入一行行的分析题解,就能明白这一段代码在做什么、为什么必须要存在在题解里。(这样提交成功率会变低,但是变低又怎么样呢,我们的目标又不是成为提交成功率最高的仔)。
当然,问其他人也可以,但是我更推荐带有具体目的性的提问,而不是“这道题怎么做?”这种宽泛的问题。一般来说,问题越具体,越好回答,被回答的几率越高。
数量还是质量?
其实都需要。一定的数量是熟练度的保证和见过大部分题型的基础。
熟练度在面试中很重要:面试一共那么长时间,其他条件不变,写代码越快,能做的其他事情就越多。其他事情可以是多跟面试官交流,回答一些 follow up,做一些优化等等。这些都是面试加分的项目。
见过大部分题型也很重要:见题型多的本质其实是对于某一类问题能否更好的抽象。比如对于堆来说,91 算法一直强调它的本质是“动态求极值”。刚读完我是不理解的,做了一道题我可能稍微有点理解了,做了三道题我就会觉得“哇塞还能这样,哦果然能这样!”拥有抽象问题的能力就等同于拥有以不变应万变的能力,在遇到没见过的题的时候就可以不慌。在面试中遇见原题的概率确实也不大,所以锻炼抽象能力很重要。
当然,刷题的质量也重要。当我们说刷题的质量的时候,我们在说什么呢?我觉得质量是指:一道题是否真的理解它在求什么。对于每一种这道题可能的思路,运用了哪些数据结构,用这种数据结构的优势和劣势在哪里。比如两数和,哈希表是常见的时间优化解法。这里利用了哈希表能用 O(1)时间获得对应 key 的值的特性,牺牲了空间复杂度,而优化了时间复杂度。
复习和重复
复习和重复是很重要的,毕竟“孰能生巧”嘛。对于我来说,每个数据类型的模板题是我写的最多的,多到我能一遍过的基础上每隔一段时间还要刷一下。我在面试之前对于每个常见的数据类型都有自己喜欢的模板写法,并且能根据每道题对模板进行改进。
我记得我当时学堆的时候觉得太难了,我就照着 91 算法讲师小漾写过的堆写了一个礼拜 — 就是从早到晚一直写的那种一个礼拜。之后我经常打趣说 “就算你半夜三点把我拉起来让我手写一个堆都不会有任何 bug”。 凑巧的是,我在面试某个 pre-ipo 公司的时候就考到了跟堆相关的知识。当时的运行环境是 hacker rank,需要把代码跑出来并且通过实例(注:并不是每个公司都要求代码能在环境中运行,有的公司面试更像在白板上写代码)。我当即给面试官表演了一段速写最大堆,因为太熟了,所以行云流水一气呵成。写完了之后我发现两位面试官的眼睛放光,后来 recruiter 主动反馈说面试结果非常非常好。在给 offer 的时候给了比申请的级别高了一点,而且最后谈薪资的时候还主动加了 12%。
有很多一起刷题的小伙伴
刷题,尤其是一开始刷题,都是令人感到困难的。很多时候这件事并不难,但是这种“好难啊”的感觉才是真正阻碍我们开始的东西。当有了很多小伙伴的时候,有了周围人的压力和鼓励,这种感觉会减弱一些。
刷题的中后期也会经常感到迷茫和焦虑,有很多小伙伴也能很好的减轻迷茫感。甚至很多时候,因为刷题群、技术群里很多大佬都上岸了,大佬们还会分享职位信息,可谓是一举两得。
对于我来说,我在决定要刷题的初期在网上加了很多技术群和刷题群。在我刷题的大部分时间里, 我每天早上睁眼看微信都是一页的刷题群未读消息。每次看到这个,我就有种我也要赶紧起床刷题的紧迫感。每次刷题觉得郁闷了,去群里跟大家聊聊天互相鼓励,也会一会儿就觉得元气满满。
在哪里找这些群呢 —- 力扣题解区有一些活跃的大佬们的刷题群都不错,力扣的讨论区也经常有人拉刷题群。
适应面试环境
就算是算法面试,和在家自己悠闲刷题的感觉还是不一样的。算法面试要求快速的锁定思路并且进行精准打击。(呃,好像游戏打多了…)这方面我强烈推荐力扣的周赛和进行一些模拟面试。模拟面试可以找朋友,也有一些提供类似服务的网站。我在 interviewing.io 模拟了三次,感觉还是挺有用的。
我现在的竞赛分大概是 1780。曾经我也很焦虑的问 Lucifer 竞赛/面试一紧张没思路怎么办。Lucifer 的回复很简单也很有效:“先打 20 场再说”。
Just do it
“先打 20 场再说”是面向面试刷题中最重要的指导思想了。 开始总是让人觉得非常困难,但是事情往往没有想的那么难。我也常常因为害怕自己“做不好”而浪费很多时间在寻找“最完美的”开始方法上 —- 实际上,当一个人开始学习某一项技能的时候,大概率这个学习方法是不完美的。所以如果你也想开始面向面试刷题,请把它想成一款游戏 —- 先开始打了再说,打了之后再根据需求和网上的攻略调整自己打游戏的方式就能慢慢变成大神啦。