首先介绍下个人情况,985本硕科班在读,无竞赛背景,刷题是兴趣爱好。目前lc刷题950+,竞赛18场2000分(神经刀选手,日常三题,运气好能卡点A完)。

下面就简要分享一下我在leetcode刷题的心路历程以提供大家参考,欢迎交流讨论。
我是从大三上开始刷题的,那时候完全没有数据结构or算法的思想,所以做题非常吃力,基本上只能想到暴力的做法。后面才有意识地针对性学习相应的数据结构和算法。做题的顺序当时也没有考虑过什么顺序,每日一题出什么我就做什么,没想到思路就直接开始cv。
这种状态一直延续到大四,大四因为没什么事情所以准备好好学一学算法于是看了点网课。其实学到什么我倒总结不出来,重点是我有了点刷题的感觉,至少在自己的努力下不看提示能把一道没做过的题目给过了我都觉得很有成就感。下面是一些个人的做题思路与经历。
其实算法题一共只有那一些知识点,如果做题目的时候能够先想到这道题想让你用什么方法做,那剩下的基本上就是代码填空了。以及做一个类型的题目很多遍不如把一个类型的代表题理解吃透,举一反三才是王道。总结一下我目前觉得比较常用的知识点以及一些印象比较深的题目(比如刚刚做过的周赛题),可能未来的某一天会出个视频每道题目都讲一讲我的做题思路。
我觉得bfs真的很重要,很多题目都会用得到,而且基本上模版基本一致,属于吃透一道题其他bfs基本都差不多了,核心就是下面这一部分。推荐的题目比如,层次遍历,岛屿数量。
queue<type> q;
q.push(root);
while (q.size()){
int size = q.size();
while(size--){
auto p = q.front();q.pop();
foo(p)
}
}这个也很重要,但是不同的dfs题目不是非常相似。需要考虑的因素比如递归出口是不是可达的,会不会无限递归。比较经典的题目比如全排列,岛屿数量,八皇后。
Note:如果是选与不选的问题,我更喜欢用状态来表示n个物品的选择问题(总共是2的n次方种方案),或者说用32位int表示状态相较于用一个vector,看起来更舒服。 and dfs的时候记得传引用(因为这个周赛tle了好多次,传值每次都会拷贝一份数据)
for(int i = 0;i<1<<n;i++){
for(int j=0;j<n;j++){
int u = i>>j&1;
if(u){
//select (i+1) product
}
}
}需要自己摸透,二分的过程是不断的缩小答案可能出现的范围(也就是说每次求mid都要删除一部分元素,不然会无限循环),才相应的对r或者l作修改。两种思路,一种是枚举数组下标,一种是枚举答案可行的范围(非常妙,仔细品味)
比较推荐的题目,在排序数组中查找元素的第一个和最后一个位置(lc 34), 每个小孩最多能分到多少糖果(lc 2226,周赛题)
属于是我觉得最难想的一些题目了,理解dp的核心思想就是减少重复计算。当前的状态可以利用之前的状态。
题目比较多,例如斐波那契数列,上楼梯,01背包。会做01背包那就会 (lc 2218 周赛题)从栈中取出 K 个硬币的最大面值和。
这两个思路其实是对立统一的,一个是求和次数多,一个是区间修改多。代码模版都非常相似,没有什么印象很深的题目,但是很多地方都需要用。尤其是对于差分有机会的话可以学一下离散化。
树状数组暂时不会,先mark一下。
其他一些题目我觉得我自己学的不够深,还需要多练练
比如:
关于周赛其实没什么好说的,我最开始的几次周赛一直坐牢,都只做了一题,因为依赖题解,看到新题没什么思路。后面逐渐养成不看题解or标签等提示,直接上手做题的习惯,慢慢的可以做两道做三道了,所以越害怕掉分就越要打周赛,给自己一点压迫感做题的效率才会高许多,面对困难题也不要害怕,至少把自己脑子里能想到的写法写出来交一发,错了就之后看题解的时候再想想为什么这个方法是错的,这样收获会更多。