当前位置: 华文星空 > 知识

大家都是如何刷 LeetCode 的?

2020-05-16知识

2020年4月更新:

跳槽告一段落,开启新的旅程。终于不用再爆肝刷题了 !之后可能只会做做周赛保持手感,毕竟将来还可能再跳槽还要面试。

TL, DR

  1. 零基础先去学一点【数据结构】,【算法设计与分析】的课程。
  2. 按题目类别集中攻克,先easy后hard,同时总结套路和模板。
  3. 注意时空复杂度,一题多解,一解多题。怎么在提交之后判断代码的时间复杂度达标呢?这里有个小tips。
  4. 高频题可以刷第二遍,第三遍。
  5. 参加周赛要趁早。

原文:

作为留学生为了找工作,16年开始使用Leetcode刷题。四年来刷题过千,经历过求职和跳槽各种面试,也曾当过面试官面试别人,有一些心得体会可以分享。

刷题进度:

2020年初 刷题进度

刷题前的 背景

  • 大陆本科,美国硕士。两个阶段的专业都是电子工程(EE)。
  • 在学校上过的跟刷题相关的课程:C++程序设计, 数据结构与算法 算法设计与分析 ,离散数学。
  • 用过的语言有C++,Java。觉得C++更顺手,于是选用了C++刷题。
  • 刷题相关的 网站&资料&工具

  • 首先是Leetcode官网了。我用的是国际版 leetcode.com。
  • 国内版leetcode-cn和国际站内容(题库,周赛)基本一致。也有不同的地方,比如国内版新增了【剑指Offer】和【Cracking the Coding Interview】的内容,也有独立举行比赛等活动,做了很多本地化的事情。
  • 国际版Discuss版面更活跃 ,有不少民间题解写的详细易懂,回帖也很及时。
  • 我在 网页编辑器里直接码 ,没有使用IDE或专业的文本编辑器。
  • 优点: 更贴近白板面试场景 ,不需要搭建测试和运行框架。
  • 缺点:没有代码补全(影响不大,刷的多了以后API都记住了),只能通过打印信息来调试,对肉眼debug能力有锻炼(不一定是个缺点啦,被逼着总结了一些常用算法模板,我现在bug也挺少的,出错也能很快定位)。
  • 两个查 STL API和库函数 的网站
  • cplusplus (更新的略慢,c++17的一些特性查不到),
  • cppreference.com(推荐) 。刷题多了,常用api就记熟了,后来就很少查这两个网站了。
  • 纸和笔 ✏ ️:想不明白的时候在纸上写写画画,帮助思考。特别是图论的题目,拿最简单的test case画出来就能帮助思考,效果拔群。
  • 手机 :倒计时功能提示时间,时间到了之后如果没有思路,或WA,或TLE,就到Discuss讨论区取经,我一般只会尝试 思考10-20分钟 。20分钟足够把解题相关的知识和技巧拿出来枚举一遍了,还想不到方案多半是因为有的知识你不知道。所以快去看答案吧。
  • 我的刷题经历大概有下面几个阶段:

    第一阶段 ,16年夏天,刷题分了三个小阶段,顺序是 easy >> medium >> hard ,题目范围是题目编号前300道里的算法题,刷完用了两个月。

  • easy 部分,熟悉了cpp的语法以及STL的用法(经常遇到记不住function名字的情况,我会查阅 Reference - C++ Reference 这个网站)。这部分题目基本能独立写出来。
  • medium 部分,重温了基础的数据结构和算法,重点总结了各种常见数据结构和算法。
  • hard部分, 很多题没有思路,需要看Discuss。
  • 刷题节奏大概是easy阶段每天12道,medium阶段一天能做8道,hard阶段随缘2~4道。( 早八点到下午六点 ,中间只有吃饭没别的活动了,晚上跟着ucb的cs61b学学java)每道题AC后,会检查运行时间。慢的话就去discuss上学习大神们的解法思路,然后自己写一遍提交。查看discuss的情况还包括:自己的代码写的很繁杂,逻辑不清晰,自己又理不顺时;题目的tag里提示有别的解法时;想了半小时以上没思路的时候。
  • 点评一下 这个刷题顺序的缺点是,没有按类别刷,难以发现同类题目的套路。 因为只有发现共性之后,才能总结出套路和模板,有了模板之后才能刷题如砍瓜切菜。可惜我后来按照Tag又刷一遍之后才意识到这个问题。所以 建议优先按题目tag刷题。

    第二阶段 ,17年春夏,按题目Tag(bfs, dfs, dp ...)把做过的题(前300题)再做一遍并总结,每个类别写了点笔记。这一遍 总结了很多常用的算法模板和套路 ,基本烂熟于心。对于每个Tag,也是按easy>>medium>>hard的顺序过的。这一阶段感受到水平显著提高:

  • 思路和代码变得更简洁:大部分题目代码量控制在50行以内。
  • 能够bug free且快速地写出常用的代码块(比如union find,dfs/bfs几个变种, binary search, partition 等等)。熟练掌握的模板和套路使我能够bug free的解决medium题目。(对于面FB这类面试题目不难但很重视bug free的公司比较重要)
  • 得益于上面一条,medium类型解题时间缩短。
  • 掌握了各种数据结构的时空复杂度 实现的难易程度 。能够选用更简单的数据结构,使得运行时间更快。时间复杂度相同的时候,能够选用更简单的数据结构,化繁为简。能用vector坚决不用unordered_map。
  • 插播一些刷题相关的小tips:

  • 和一些朋友讨论刷题策略,我们的共识是 精刷是很有必要的 。300题刷2遍吃透要好过600题只刷一遍。
  • 关于刷题的强度。一天一道题这种节奏很难坚持下来,也很难总结出套路和模板。 有条件的一定要集中时间刷。
  • 有人可能会疑惑,我的进步是因为见过类似的题,而不是因为分析问题的水平提高了。我的回答是, 见多识广也是能力,熟练套路不等于生搬硬套 ,能快速识别出题目套路并解决已经不错,活用知识甚至发明算法则需要更深入的理解。
  • 第三阶段 ,18年找到了一家小公司做软件工程师,入职后发现不太满意,于是打定主意跳槽。18年秋季开始至19年中,每周 参与leetcode contest ,保持手感。

  • 18年秋到19年初,周赛只能过三道题(hard题要么没思路要么TLE)。赛后写篇笔记,分析一下遇到的问题。这阶段应该不能算是刷题了(我理解的刷题是短时间内做很多题)。不过 一年contest做满的话也有200多道题了
  • 19年初在 洛谷练习场 做了几个专题,DP,图论,线段树。参加了google code jam,Round 2被刷。买了几本算法竞赛的书,看了些基础内容。这些支线剧情对leetcode刷题帮助有限, 如果你发现可以用oi或者acm的高级算法解面试题,那么多半是你想多了。 当然面试官会对你印象深刻,但他可能并不能听懂你的高级算法或数据结构,并要求你解释到他听懂为止,这其实暗藏风险。实际上,他只是希望你能用常规的办法做出来。这里我想说的是:如果你本来就没搞过算法竞赛,就不要去学这些,耗费很多时间但收益有限。如果你是竞赛大神,你可以先抛出一个你和面试官都理解的常规解法,时间充裕的话,可以再提出你觉得更牛的解法。以线段树为例,LeetCode虽然有线段树的题目,但是一般有更基础,且复杂度相当的解法。又比如Campus Bike这个题,可以用Hungarian 算法,也可以用DP,面试中能答出DP就已经稳了。
  • 第四阶段, 19年下半年 集中刷题准备跳槽 ,同时投简历约面试。

  • 这个阶段主要刷公司tag的题目和面经。刷题强度很大,特别是面试前一个月,每天10+道medium/hard题。
  • contest结束就看discuss,跟朋友讨论,问题不会留到第二天。大部分情况下能做完4道题,进入global前300。
  • 除了刷leetcode,没那么忙的时候学习了【算法导论】的图论章节和字符串匹配章节。【算导】的图遍历讲的不错,图的遍历是很多图算法的基础,但是我之前掌握的不好。不过面试很少考察图论和字符串匹配的,看这些只是出于兴趣。
  • 刷了这么多题目,面试也并非一帆风顺,毕竟算法只是面试的一部分。挂了几家公司后,终于在2020年初收获offer。
  • 2019年的刷题分布图

    Q&A

    什么是Leetcode周赛?

  • leetcode 每周有一次周赛,每两周有一次双周赛。都是90分钟4道题目,一般一道easy,两道medium,一道hard,每道题根据难度不同设置不同分值。比赛有实时排名,根据分值和时间计算排名,每个错误提交会导致5分钟罚时。
  • 难度落在面试的范围内,和题库的难度范围一致,低于算法竞赛。手速快和bug-free显得更加重要。
  • 为什么我建议参加LeetCode周赛?

  • 周赛中的题目都是会进入题库的,有些周赛题目将来会变为仅会员可见,换言之,参加周赛可以免费做新题。
  • 赛后可以看到所有参赛选手的提交,包括排名第一页大佬们的题解,利于开阔眼界。
  • 幸运的话,你可以在面试里遇到刚做过的周赛题(别问我怎么知道。
  • 完成「最优解「到」最好写的最优解「的跨越。
  • 如果你没有算法竞赛经历,不管你之前题目刷的多熟,总是要参加个十几场才能找到感觉,所以要趁早。
  • 刷LeetCode就能应付面试了吗,还需要做什么?

  • 大部分人刷leetcode的目的是为了在面试(无论是OA还是电面还是onsite)的算法环节成功。但是实际的面试场景要比网页上做题复杂的多。通过leetcode训练可以提高解题的硬实力,但还有一些软的方面(交流,沟通,开发习惯)leetcode环境无法模拟:
  • 和面试官讨论清楚题意,输入输出,corner case
  • 把思路完整展现给面试官,实现前把算法讲明白,复杂度分析;
  • 尽量bug-free的实现算法,尽量的易读,呈现好的代码风格;
  • 展现出好的开发习惯,如设计合理的testcase,并在白板上手工测试
  • follow up 问题的交流讨论。
  • 因此,只靠leetcode准备算法面试是不够的,找有经验的人帮你模拟面试能够让你发现不足。此外别人的面经和自己的亲身经历也十分重要,特别对于找第一份工作的毕业生来说,多看面经多面试总没有错。
  • 面试也不是只有coding,也有behavior question,系统设计甚至专业领域知识等等。系统设计更难准备。
  • 祝大家拿到满意的Offer!