写在前面,由于我们知道经常出现的算法是有限的,而题目是无限的,所以本文章主要服务于我自己去记录对于某OJ的总结,包含以下几个OJ网站:luogu.com.cn,北大OJPKU JudgeOnline,cf,力扣 (LeetCode) ,掘金,牛客网等网站,个人会做好一个大分类,比如某某题来源于哪里,如果没写就是我在一些书上或者一些有趣的例子上淘到的题目。
市面上的算法刷题实际上很多,但是我觉得这种普遍的刷题并不能给我们带来什么,很多同学也在刷完题后变成了“硬套”,这种在DP中屡见不鲜,所以本仓库主要是服务于想要学习好某个部分的同学/有兴趣的OIer,当然,还有我自己这个老登。
关于上传,我现在倾向的格式是POJ就简单做POJ,leetcode简写成LC,CodeForce简写作CF,以此类推,不过掘金我决定写成WG ,也就是代号+ +题号+题目+解法(可选) +解法序号(提供一题多解) 2025/12/26
算是C++里面最友善的一个OJ了,可以用#include<bits/stdc++.h>万能文件头,但是题解有时候参差不齐。题目类型官方有整理好,但是我觉得缺少一定的难度或者说难度也比较层次不齐。
Poj比较简洁,中规中矩,英文居多,适合ACMER去玩。个人Poj的题目也不是写很多,所以没有什么说服力。
个人认为cf的精髓就在于比赛,cf的比赛有四种级别:div1,div2,div3,div4(有时会有div1+2,除此之外的unrated暂且不论),难度呈递减。div1最难,因此只有rating1900+才有资格参加;div2是大多数普通acmer可以参加的难度;div3是比较简单的划水场,当你rating1600+就unrated了;div4是最简单的养老场,算法入门后就不靠它涨分了。
好处在于不用写一些头,对于cpp比较友好,各种头文件已经预先写好了,放心食用即可。
题解多样,对于求职或者面试来讲,刷热门100和算法150即可,如果有更高的要求,可以自行拓展题目。
相对于前面的OJ来看,掘金的亮点仅在于有AI校对的功能,但是截至目前我做题的情况来看,掘金的题目质量有高有低,分类来看是比较好的,缺点在于AI不够智能,在一些较难的题目中也经常容易自乱阵脚,推荐有一定代码基础的人做。
OJ的题目偏向于语法,对于不熟悉某一语言的语法可以先用牛客写,个人推荐使用python,或者一些陌生语言可以先通过几道编程题的编写来熟悉编程的OJ或者一些常用语法,如python:
str1=input().split()
str1.insert(0,"Allen")
print(str1)(1)输入
使用input()函数获取用户输入
(2)创建列表
使用split函数,对获取到的用户输入,以空格为间隔,创建一个列表
(3)添加到列表最前面
使用insert函数,将需要添加的内容(字符串'Allen'),添加到列表最前面
函数用法:需要添加内容的列表.insert(添加的位置,添加的内容)
(4)输出完整列表
使用print函数,输出列表
实际上数组在CS61B中是一个不错的数据存储,甚至置于链表之后去讲解,其也是Hash等数据结构的基础,也可以用数组去实现两个栈共用一个数组,也可用一个数组去实现链表(这要求我们用下标还有一些神奇的结构去实现)
拓扑排序 欧拉图
图的连通性 基环树 2-SAT 最大流 二分图 最小割 费用流
Tip
对比一下DFS和BFS:
- DFS的优势:DFS能搜索出从入口到出口的所有路径,BFS不行。不过,因为路径数量多,很少有题目要求输出所有路径或者输出路径数量。
- BFS能够快速找到最短路径,时间复杂度为$O(N+M)$,N为N个顶点,M为M条边。 DFS我们一般用递归实现,BFS我们用队列去实现。
双向广度搜索,BFS与优先队列,BFS与双端队列,IDDFS,IDA*,A*算法
我们知道DFS的计算量庞大,这时候我们采用剪枝的形式来减少计算量,我们把不可能的产生答案的条件剔除掉称之为剪枝。这跟插花的剪枝很像,我们要知道剪掉哪个枝条,以及在哪剪。 常见的有
- 可行性剪枝。对当前状态进行检查,如果当前条件不合法就不再进行
- 搜索顺序剪纸。搜索树有多个层次和分支,不同的搜索顺序会产生不同的搜索树形态,复杂度也相差很大。
- 最优性剪纸。在最优化问题的搜索过程中,如果当前花费的代价已经超过了预期花费,那么本次搜索就没有进行下去的意义。、
- 排除等效冗余。搜索不同的分支,如果结果是一样的,那么只搜索一个分支即可。
- 记忆化搜索。在递归的过程中有许多分支被反复计算,使用记忆化搜索可以减少重复运算。
BFS本质是一个求最短路径的算法,其求最短路径有一个前提:任意连接的顶点其边长相等,其复杂度为$O(N)$。 一般以两类题目为主:
- 最短路径的长度。答案唯一,路径长度即为路径结果顶点的数量
- 最短路径具体经过哪个顶点。由于最短路径可能有多条,一般输出字典序最小的那条路径。 还可以有以下场景:
- 求点1到其他店的最短路径,执行一次bfs即可
- 求任意点i到0的最短路径,相当于在反图上求起点0到其他所有点的最短路径
- 求任意点i到n+1的最短路径,相当于在反图上求起点n+1到其他所有点的最短路径
注意,用BFS的队列要判重,一般编码时定义
int vis[n]来判断是否已经用队列处理,若vis[i]=1,表示i已经用队列处理过,i不再进入队列。
int inf=0x3f3f3f它比n=10^3大,如果是int inf=0x3f3f3f3f,其数值是10^9.
在图论算法中,例如 Dijkstra 最短路径算法,你会用一个数组 dist 来存储从起点到所有其他顶点的距离。为了表示最开始所有距离都为无穷大,通常会将 dist 数组初始化为 0x3f3f3f3f。
中级:数位统计DP,状态压缩DP,区间DP,树形DP,概率DP 高级:单调队列优化,斜率优化,四边形不等式优化
矩阵快速幂、高斯消元、鸽巢原理、二项式定理、杨辉三角 矩阵的应用、异或空间线性基、0/1分数规划、线性丢番图方程、同余、威尔逊定理、整除分块、卢卡斯定理、容斥原理、Catalan数、Stirling数、二维几何、圆、高等数学、概率论 积性函数、欧拉函数、迪利克雷卷积、莫比乌斯函数、莫比乌斯反演、杜教筛、Burnside定理、Polya定理、母函数、公平组合游戏、三维几何