算法入门 2: 力扣刷题技巧

1,152 阅读11分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

上篇文章 算法入门 1: 推荐一个帮我两个月 AK 力扣周赛的算法仓库 聊了下,如何做好刷题前的准备

这篇文章我们聊一下怎么去刷题

这里主要是以我自己刷题的经验来讲,比较适合有时间投入进去,跟一个个算法死磕过去的情况.所以可能不太合适希望速成的同学.

对于算法入门,我将其分为两个阶段,学习和训练,学习阶段主要是对于算法小白而言(就像我刚开始刷算法的时候,那时候对于算法我啥也不懂,连链表都没什么概念,所以这个阶段主要是需要去学习算法知识).而在学会了一个算法之后,就需要通过训练去提升对于算法的熟练度.

学习

  • 目标: 学习基础的算法相关的知识,掌握基础的编程能力,掌握基础的解题能力

刚开始,很可能大多数题连思路都没有的,这时候不要去硬想,直接去看题解,这是学习的过程.

就像我们在学数学时,不会先去做练习题,而是先去学会了加减乘除之后,再去做练习题.学习算法也一样,先得学算法,再用算法去解题.

而至于怎么学习?如果自己能找到一个合适自己比较体系化的学习知识的地方是最好的了.比如算法相关的书籍,网上的课程,在线的视频等等. 不过没有也没关系,力扣上每个题后面对应着几百几千的题解,这些完全可以当作学习的地方.

题解区里面各位写题解的大佬才华横溢,有从专业方面去论证的,有写的通俗易懂的,有的图片做的很生动,有的用视频讲解.总有一篇题解是对你胃口的.

看题解的过程,就是学习的过程,当然有时候会遇到某些完全搞不懂的一些词,特别是刚开始的时候,这也是需要去学习的点,如果题解中有解释,可以看题解中的解释理解,或者看看别的题解.如果是这道题相关的,一般都会有解释,不过就算没有,也没关系,直接谷歌或者百度去搜这个关键词,找相关的资料学习理解.

在看题解的过程中,有可能有些知识点是比较难啃的,或者有些思路一下比较难以理解,则需要重复去看,或者多看几篇不同的题解,可以通过在纸上模拟代码运行的过程,以及其中的数据的变化.当然也可以直接在本地将代码打出来,利用 VSCode 的调试功能,一步步去执行代码会更为直观一些.

在理解了思路之后,就需要自己能在不看题解的情况,把题给写出来.做到这一步,才算是基本的刷了一道题.之后就是需要每过一段时间回来重复刷一次,防止到时候忘了,毕竟记忆这东西有时候不是很靠谱.

如果一道题这样完整的做下来,至少这道题的思路算法应该是基本掌握了,并且基本的编程能力也是能得到一定训练的.

或者对自己的要求更高一些的话,可以把下面进阶中的步骤也练一练,比如计算时间空间复杂度,优化代码等等

上面的步骤中,也不是一定一成不变的,如果有些题自己有思路的,可以按照自己的思路尝试自己先解出来,然后在去对比题解中的思路的解法,以及代码,看自己写的怎么样,有没有哪些需要优化的.

毕竟我们最终的目的是能够自己独立的解题,这就需要去训练自己解题的能力,解题的能力可能就不像前面两种能力比较容易训练,只能靠自己一题题解过去,积累自己的经验.

对于不同的题,会有不同的思路,或者不同的人也会有自己不同的习惯.这里分享一下我平常解题的思路

我的思路一般先看这题是不是可以用我所会的算法去解,如果感觉可以的话,比较简单的就直接尝试在脑中去想,甚至可以想想怎么做会更优一些;如果是比较难的,可能就需要到纸上去模拟一些简单的情况,看能不能用这个思路解掉,然后尝试写代码去解.如果这题没有让我有比较直观知道能用哪种算法解的话,或者题目本身比较混乱的话,一般就是直接根据题目的描述,根据给出的部分样例去模拟一个过程,在这个过程中去慢慢理解题意和思考解法,实在不行,就直接用朴素解法,用代码把这个过程模拟出来,然后在去一步步优化.

当然这个是我对这个题有个大概的思路的情况下,有些题如果是完全没有思路的,我就直接放弃去看题解了.有些题纯粹属于脑筋急转弯或者有些题的解法太巧妙了,如果没遇到过,可能怎么也想不出来,这种题就没必要去死磕了,靠多刷题,去记住它,然后攻克它.比如 237. 删除链表中的节点,第一次做的时候,我想了一会儿没想出来果断去看题解了,这种一点思路都没有的简单题,如果不看题解,我估计想个半小时都不一定能想出来怎么解的.

另外可能有些题有思路,代码也能写出来,但就是过不了,这时候一般也建议不要去死磕,可能就是一个小细节没有注意到,或者说有可能是思路就是错的.直接去看题解好了.比如 375. 猜数字大小 II 这题,等我在二分的路上调试了半个小时之后去看题解,才发现从一开始就是错的.如何确定题目所用的算法也是一个需要训练的能力,需要靠总结各种算法之间的区别,以及多刷题,靠题量去训练,这个得慢慢来.

训练

  • 目标: 提升使用算法的熟练度

一开始可以跟着题解去敲代码,不过等自己理解了思路之后,一定得在不看题解的情况下,把题给写出来.一般这需要重复刷个几遍,特别是学习一个新的算法或者思路的时候,多做几遍,直到自己能够熟练的做出来.

当自己能根据思路把题写出来时,对当前这个算法已经有了基本的掌握,这时候可以考虑去提升运用算法的熟练度.通过专门做当前算法相关的题来训练.这些不同的题之前有一定的相似,又有不同,这样能训练算法在不同的情况如何去使用.这个需要根据自己对算法的掌握情况,去适当的调整.比如对我来说动态规划比较难掌握,我就花了半个月左右的时间专门去刷(主要是每天就刷一两道,所以刷的比较慢).

进阶

很多题能使用的算法不止一种,当我们用一种算法刷过某一题,在之后学习了新的算法,又会回头来刷,这时候可以试着去对比不同算法,对比不同的算法之间的优劣,主要是时间复杂度和空间复杂度,一般来说我们会以时间复杂度作为更优的参考,如果时间复杂度一样的情况下,会去考虑更优的空间复杂度.至于具体时间复杂度和空间复杂度是怎么计算的,大家可以到网上搜一搜,这方面让我讲估计也不太专业,目前我也就部分题能自己算出来.

学会计算时间空间复杂度之后,就能对比各个算法之间的优劣,这样在之后刷题的过程,如果某些题同时有多种算法可以解,就可以去判断用哪种算法会更好了.

我们可以通过去看别人写的代码,在题解中有很多别人的解法和代码,而点赞靠前的大多数都是大家觉得写的比较好的代码,可以去对比自己写的和别人写的有哪些区别,是不是有更简洁或者逻辑更清晰的写法,多做这样的对比,可以提高自己的编程能力.(可以多看看一些高点赞的题解,以及可以通过标签,选择自己所使用的语言的题解)

另外力扣不止有国服,还有外服的,其中也会有很多优秀的代码.只要将题目链接中的 -cn 去掉即可跳转到外服.不过有个比较烦人的地方,就是跳到外服之后,会自动跳回国服,得需要重新打开一遍外服的链接.大家可以看下我 GitHub 上写的 方法,屏蔽掉https://leetcode.com/static/cn.js就能防止这种自动跳转.

国服: https://leetcode-cn.com/problems/two-sum/

外服: https://leetcode.com/problems/two-sum/

遇到瓶颈怎么办?

就是一道题死活想不到思路,就是看了题解依然理不清思路的,但又必须要攻克它.比如我之前刷动态规划的题,遇到123.买卖股票的最佳时机-iii这题,即便看了官方题解,依然是转不过弯来.我的办法就是多看,把几个题解都看一遍,直到看到股票系列的通用解法,眼前一亮,就悟了,感觉就像任督二脉被打通了一样.这题让我从只会用一维的状态数组,学会去理解多维状态数组.

后来我回想了下,并不是单单靠这篇题解让我想通了,而是之前看的其他题解,虽然很多地方当时并没有相通,但是如果没有之前在其他题解中看到的知识做垫底,而是直接看这篇题解,我估计我不一定能一下子相通.

所以我遇到瓶颈的时候,就是去多看,可以看国服的题解,可以去外看服的题解,还可以根据这个题目去搜相关的博客,去哔哩哔哩搜相关的视频,以及根据这道题中所用的算法,去搜相关的算法的文章.

看完一个题解或者一个文章后,还是没有想通,也不要着急,这些都是在做积累,可能有些文章表述的不是很清楚或者自己没有注意到重点等等原因,但其中有一部分知识自己已经默默的吸收了,直到看到一篇能让自己茅塞顿开的文章,这些之前积累的知识就会全部串联起来,也就突破了这个瓶颈.

总结

主要原则就是重复,通过不断重复的过程,慢慢去学习和掌握算法.

  1. 如果自己没有思路,不要去硬想,直接去看题解.如果一篇看不懂,就多看几篇.
  2. 学会和理解思路之后,一定要能够自己独立去实现出来.然后每过一段时间回来再刷一遍.
  3. 通过专题训练去练习对算法的使用.不断去重复使用算法.
  4. 进阶: 对于不同的算法,去分析其时间空间复杂度.考虑最优解.
  5. 进阶: 学会优化代码,优化时间复杂度,优化空间复杂度,状态压缩等等