网站
https://leetcode.com/
https://leetcode-cn.com/
https://binarysearch.com/
当然国内外还有非常多类似的OJ网站。选择一两个即可,不必贪多。
感想(2021.05.30):
从2020.08开始leetcode.com,从2021.01开始leetcode-cn.com,中间基本没怎么停过,偶尔会有断签。
目前国内200+,国外400+。
从开始的痛苦,到现在慢慢有成就感,刷题已经是一种习惯。
开始Easy都写不出来。英文的题目也看不懂,很多单词不知道什么意思。
到现在,Easy基本没问题,Medium很多也能写出来了,Hard也慢慢有了思路,有些也能写个七七八八。很有成就感!
现在,很多英文题不查单词也基本都懂了。个别单词不懂,有时不影响理解题意。
原因可能有两个。
1、题目刷得比较多了。英语题解看的也挺多了,很多术语都知道什么意思了。同时,工作的原因,每天找问题基本都是Google看的英文文档。
2、从2020.07一直以来的《每日英语听力》APP打开,基本没间断过。
从开通VIP当天开始计算,已经连续打卡260天,累计打卡361天。
刷题的好处:
熟悉各种算法,写出来的程序更优。
用力扣刷题的好处:
可以打印中间变量的值。
可以自动跑很多cases,从而可以很快验证自己的算法是不是正确的。有没有考虑到所有情况。
双周赛等比赛,排名高了容易进大厂。
方法:
0、要不要看别人的答案?看别人的答案是不是就很愧疚,就感觉自己很傻很蠢,不如别人?
当然不是!!!在自己思考之后,还是没有很好的思路,看别人的题解是快速学习并提升自己的方式。别人的题解往往有很多思路,不同解法。这对自己的提升是有百利而无一害的。
历史上非常多优秀的算法,都是这些名人花费好长时间才想到的,甚至需要很多灵感和天马行空的想象。
如果自己没见过的算法,自己空想一辈子可能也想不出来。请站在巨人的肩膀上。
看了很多优秀的算法,可能就会有自己的想法。那就尽情开始畅想吧。
0.1、自己思考多长时间去看别人的答案呢?
针对不同的题,可以有不同的时间。简单题,直来直往的,五分钟/十分钟/二十分钟还没有自己想法,直接去看吧,别浪费自己的青春。
Medium/Hard,自己完全没思路的,直接去看吧。有思路的,自己写写调试看看。 或者想个半天/一天也是ok的。
1、测试驱动开发。编写测试用例,尽量多地想各种edge/corner cases。
2、画图。画画图就有思路了,很快就知道怎么写了。在草稿纸上随便画。
3、刷透一题。一题多解。掌握不同解法。国内外两个网站的题解,交叉着看,相互补充,同时熟悉相应术语中英文如何翻译。
4、多语言。算法思想都是一样的。目的是熟悉不同编程语言的库和写法。同时避免只有某一种语言的解法,自己看不懂。
5、优化。分析每种解法的时空复杂度(时间复杂度和空间复杂度)。能否降低时间复杂度?空间换时间。
没思路的时候改怎么办?
a、尝试暴力。
b、把知道的算法都罗列一遍,对于每一种,想一下行不行?二分/DP/DFS/BFS/Two Pointers/Sliding Window/并查集/…
有时候有些题往往需要想象力和创造力。
贪心思想(Greedy):
其实写程序的时候不知不觉就用了贪心思想。比如,尽可能较少步数到达最远方。尽可能剪枝优化,减少搜索空间。尽可能降低时空复杂度。
各种DP:
线性DP;区间DP;背包DP;树形DP;状态压缩DP;数位DP;计数型DP;递推型DP;概率型DP;博弈型DP;记忆化搜索;
ref [https://zhuanlan.zhihu.com/p/126546914]
计算机的优势:有固定模式的重复性计算。这对于DP的这种状态转移和DFS这种递归的算法是极其方便的。
两大类:
- 递推/Iteration/DP
- 递归/Recursion/Backtracking(回溯)/+记忆化memo
两者往往可以相互转化。
经验
有些题目一看到,就会意识到用哪种算法。
比如,树 => DFS/BFS;
字符串的括号匹配 => Stack;
有序数组 => 二分;
最少的步数到达目标状态 => BFS(deque);
分组/岛屿个数 => 并查集;
求和 + 区间范围 => 前缀和;
二维数组 => DFS/BFS;
链表题,往往需要切割再重组节点之间的关系,要处理好指针的移动。同时也有别的技巧,比如快慢双指针等。
TODO
分治法。很多递归的算法已经用到了分治的思想。
线段树
树状数组
模拟退火算法
遗传算法
博弈论
进阶
博弈论
A-star
线段树
树状数组
前缀字典/字典树/Trie
双向BFS
重复的力量
第一次懵懵懂懂(卧槽!这么牛逼的想法怎么想到的)
第二次稍微理解
第三次轻车熟路
策略
1、很多题目都需要再次复习温习,去掌握各种不同优秀的解法和暴力的解法。
2、手动写各种case,手动写下算法迭代过程中的每一步中间结果,可更好地理解该算法。