leetcode刷题什么水平(大神教你LeetCode正确的刷题顺序)
作者| 慕课网精英讲师 liuyubobobo
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!
首先,如果你的时间特别紧,直接刷题当然没有问题。但我的经验是,如果你有相对宽裕的一些时间,除了想准备算法面试以外,还想真正把算法和数据结构的基础打扎实,应该先认真学习经典的算法和数据结构的底层原理。如果你的时间特别紧,可以直接跳到下面第二部分,“刷题篇”。
01
认真学习复习
算法和数据结构的底层原理
什么叫经典的算法和数据结构的底层原理?我简单总结了一下,主要包括以下内容:
- 各种排序算法,所谓的十大经典排序算法;
- 二分搜索法;
- 线性数据结构:动态数组,链表,栈和队列;
- 常用的树形数据结构:二分搜索树,堆,红黑树,B 树,并查集等;
- 哈希表;
- 常用字符串算法,如 Trie 的使用,滚动哈希,KMP 等;
- 基础的图论算法,如图的深度优先遍历,广度优先遍历,及其应用;带权图最短路径的 Dijkstra 算法;最小生成树的 Kruskal 算法;有向图的拓扑排序;哈密尔顿回路(或者路径)等等;
- 一些进阶的数据结构,如线段树,后缀树,跳表,等等;
- 一些进阶的图论算法,如寻找桥或者割点;欧拉回路(或者路径);匈牙利算法;最大流最小割;等等。
- 其他算法,比如随机算法 Knuth Suffle,蓄水池抽样,等等
很多同学看这个列表,会觉得“枯燥”,甚至觉得“轻视”。这看似都是课本上最基础的内容,也好想和见到的大多数面试题没有关系?但是,我的经验是,对这些“基础问题”的掌握,既是刷题的基础,也是继续深入计算机科学其他领域的关键。
首先,这里面的很多内容,是刷题涉及不到的。比如在刷题的时候,基本不会遇到让你实现一个排序算法的情况,如果需要排序,通常是直接调用语言的标准库就好了。但是,我知道很多厂子的面试问题,恰恰就是“讲一讲快速排序是怎么回事儿,归并排序是怎么回事儿,红黑树的基本原理”,等等这类问题。
另一方面,其实对这些基础的算法和数据结构的学习,很多时候并不完全是学习一个算法这么简单,而蕴含着对算法思想的学习。我们可以看到,为了解决一个问题,我们可以如何设计算法。
最典型的例子就是递归。很多同学都觉得递归很绕。但是,在我列的这个列表中,所有的算法如果真的踏踏实实都搞明白了,我相信对递归是不怕的。无论是学习快速排序和归并排序,还是实现各种树结构中的基本操作,都在不停地使用递归。我们在学习这些内容的时候,并非是简单的死记硬背,而是在看一些算法思想的具体应用。
这样的例子数不胜数:
- Dijkstra 和 Prim 算法蕴含着动态规划的思想;
- Kruskal 算法蕴含着贪心的思想;
- 滚动哈希蕴含着双指针的思想;
- 哈希表,滚动哈希,都蕴含着哈希方式的运用;
- 计数排序,基数排序,桶排序,哈希表,都有对数据元素进行分类(桶)这种思想的应用;
- 哈密尔顿回路(或者路径)可以使用回溯法求解,进而可以使用记忆华搜索或者动态规划做优化,这背后也包含状态压缩的思想;
- 同样解决 topK 问题,使用优先队列和使用快排的改进思想,可以让我们理解在线算法和离线算法;
更关键的是,在大多数时候,这些所谓的基础,是进一步学习计算机科学的关键,而不是那些“稀奇古怪”的“刷题”问题。
而且,这本身也是学习算法和数据结构的核心目标——进一步去学习计算机领域其他更深入的知识。我的经验是,很多同学看似刷了很多题,但其实基础不牢靠;这就像很多同学为了考研,数学做了很多题,但是真的在论文中看到数学公式;或者实际项目中,需要用数学做一个建模的时候,还是会很头疼,一个道理。归根到底,是过早的刷题,只是以应试为导向,对这些基础的内容,理解得并不深入。
关于这些基础的算法和数据结构的学习,最推荐的教材,就是大名鼎鼎的《算法 4》。
不夸张地说,这本书我认为学习计算机的同学,不管是不是科班,都应该通读。当然,这本书在我看来是有一定的缺点的。
比如 Prim 算法和 Dijkstra 算法使用索引堆实现,虽然复杂度更优一些,但是索引堆这种数据结构稍微绕一些,在一般语言的标准库中也不提供。而 Prim 算法和 Dijkstra 算法都可以使用普通的优先队列实现,相关的方式这本书却没有介绍。
再比如对于 KMP 算法,这本书介绍的是使用自动机的方式完成,但其实,KMP 算法有更简洁的实现方式,使用所谓的 LPS 数组(Longest Proper Prefix which is Suffix),《算法4》对此没有提及。
但瑕不掩瑜,《算法4》仍然是学习经典的算法和数据结构底层实现的最佳书籍。而且这本书对新手足够友好,有 Java 语言基础的同学就可以直接看。
02
Leetcode 刷题篇
刷题关注的内容,和学习经典算法和数据结构的底层实现不太一样。
整体来说,刷题的核心,是算法设计。所以,在刷题的过程中,大家可能很难遇到诸如实现一个哈希表或者实现一个快速排序这样的问题。想排序,想使用哈希表,大家直接调用语言的标准库就好了。但是,如何使用这些经典的算法和数据结构解决问题,是另一回事儿。
另一方面,算法设计领域涉及的一些问题,也是学习经典算法和数据结构的底层实现不太能系统接触的。最典型的就是动态规划,分支限界,这些算法设计思想。
有一些基础的算法或者数据结构的应用,也是在学习底层实现的时候不涉及的。最典型的例子是栈。栈的底层实现非常简单。但是,我们可以使用栈,巧妙地解决一些问题。比如用单调栈的思想,来求解区间的最大最小值问题,或者离线解决 RMQ 问题。
对于算法设计来说,如果大家想系统学习的话,书籍方面,我推荐这本 Algorithm Design Mannual。
这本书在疫情期间,出版社 Springer 可以免费让大家下载其英文原版。如果能看英文原版的同学,大家在网上一搜,应该有很多。想看中文版的同学,这本书国内也有引进,在这里:
但是,因为算法设计是一个太广泛,也没有具体范围的领域,所以,这样的书,也不可能涵盖所有的问题。尤其是以面试为导向的话,刷题还是需要的。
刷题按照什么顺序刷?我个人建议按照 Leetcode 给大家提供的专题顺序刷。大家点击力扣中文站的“学习”标签,就可以看到力扣为大家总结的各个专题。大家可以按照自己感兴趣的(或者薄弱的)专题刷。
在这里,我列一个最基本的顺序,大家可以参考。(我特意选择的是免费内容,对于其中的付费内容,大家可以根据实际情况自行选择。)
数组和字符串
数组类算法
栈和队列
链表
二分查找
堆
递归
二叉树
二分搜索树
N叉树
前缀树
哈希表
查找表类算法
深度优先
广度优先
动态规划1
动态规划2
初级算法
中级算法
高级算法
说实话,这些专题的问题已经相当多了。如果都能刷完,并且每个问题认真理解了,我觉得算法面试的问题已经不大了。
大家可以根据自己的情况,包括时间的多少,每个专题觉得自己刷得差不多了,就进入下一个专题。
而如果大家觉得自己各类问题都见过一些了,我建议在适当时候,进入下一阶段。
03
Leetcode 竞赛
从面试准备的角度看,单纯的按照专题刷题,是有问题的。
因为,一个问题的标签本身,其实是包含巨大信息量的,是一个很重要的提示。而大家在实际的笔试面试中,是没有这个提示信息的。
比如,如果直接告诉你,一个问题是动态规划,那么大家就可以直接去思考:怎么设计状态,状态转移是怎样的。这其实将问题简化了。如果没有这个标签,很多同学可能想不到这是一个 dp 问题。
在算法设计领域,这类问题特别多。另外一个典型的例子是二分搜索。对于一些问题,没有经验的同学,可能很难想到使用二分搜索去解决,但是一旦告诉你这个问题可以用二分搜索解决,其实就没什么难度了。
对此,我的建议是:刷题到一定程度以后,可以开始尝试做力扣(LeetCode)的周赛。甚至,有些同学时间紧,可能只有一个月的时间,没有时间专门系统地对每一类问题进行练习,我都直接建议,做周赛就好了。
大家可以把力扣(LeetCode)的每一次周赛,都看作是一场实际的算法面试的模拟。
力扣(LeetCode)的周赛每期四个问题,问题质量都很高。每场比赛的问题类型不定,没有标签。大家在做的时候,需要从头分析,每个问题需要使用什么算法解决。这在我看来,是非常重要的一个训练。
在这个过程中,如果发现自己对某一个类型的问题不熟悉,可以再回头,有针对性地根据专题进行“特训”。
但是,大家也要注意,现在力扣周赛的一些问题,尤其是 Hard 问题,越来越偏竞赛问题,这种竞赛问题,在面试中出现的概率极低。所以整体,我认为,大家如果能在周赛中,做到稳定做出三道问题,应付大多数算法面试已经够了。
如果对 Hard 级别的问题感兴趣,整体上,在力扣上,题号越靠前的 Hard 问题,会相对“简单”一些,也更“标准”一些,更容易是面试过程中可能考察的问题。而相对比较新的问题,在最近一年,Leetcode 周赛的 Hard 问题,个人认为越来越偏竞赛问题。
当然如果有同学对竞赛问题感兴趣,也可以学习。当然,如何深入学习训练算法竞赛,就完全是另一个话题了。
有机会再和大家分享吧。有帮助的话记得【转发】【点赞】哦,大家加油!
欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员。
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com