这是我的个人算法竞赛仓库,主要记录算法学习、专题训练、日常刷题以及比赛过程中完成的 C++ 代码。
仓库中的内容来自长期的算法训练,而不是为了整理项目临时创建。代码覆盖基础算法、动态规划、数据结构、图论、数论、字符串、树上算法等多个方向,也包含来自不同 Online Judge 和竞赛平台的题目。
我希望通过这个仓库持续保存自己的算法积累,同时也能够比较直观地展示自己的算法基础、代码实现能力以及解决问题的经验。
目前仓库中已经涉及的主要算法与数据结构包括:
| 方向 | 主要内容 |
|---|---|
| 基础算法 | 枚举、模拟、二分、双指针、前缀和、差分、位运算 |
| 搜索 | DFS、BFS、回溯、Flood Fill、记忆化搜索 |
| 贪心 | 排序贪心、区间贪心、推公式、交换思想 |
| 动态规划 | 线性 DP、背包 DP、区间 DP、树形 DP、状态压缩 DP、轮廓线 DP |
| 数据结构 | 栈、队列、堆、并查集、单调栈、单调队列、树状数组、ST 表、线段树 |
| 图论 | 最短路、最小生成树、拓扑排序、连通性问题 |
| 树上算法 | DFS、倍增、LCA、Tarjan |
| 数学与数论 | GCD、EXGCD、快速幂、质因数分解、筛法、欧拉函数、高精度、组合数学 |
| 字符串 | 字符串处理、模式匹配、KMP |
这些内容并不是单独保存的算法模板,仓库中更多的是对应算法在实际题目中的使用和组合。
仓库中的题目主要来自:
- 洛谷
- 牛客
- LeetCode
- 蓝桥杯 / 蓝桥云课
- Codeforces
- AtCoder
- ICPC
- CCPC
- UVA
- 其他算法训练题和比赛题
不同平台只是题目的来源。我更关注的是题目背后的算法模型,而不是单纯按照平台刷题。因此,同一种算法往往会通过多道不同形式的题目进行训练。
核心代码主要存放在:
solutions/
大多数题目采用 一道题 / 一个 C++ 文件 的方式保存。文件通常包含题目编号、题目名称、算法特征或来源等信息,前面的编号主要按照个人做题顺序排列。
这个仓库也因此保留了比较完整的学习轨迹。从早期基础题,到后续的数据结构、图论、动态规划以及综合算法题,可以看到不同阶段的代码实现和算法使用方式。
这个仓库最主要记录三类内容。
学习一个新的算法或数据结构以后,通过实际题目完成理解、实现和应用,而不是只保存一份模板。
例如:
- ST 表不仅仅是写出倍增数组,还需要理解区间长度和循环边界;
- LCA 不只是记住模板,还需要掌握树的建图、深度维护和倍增关系;
- 最小生成树、并查集、LCA 等算法也可能出现在同一道综合题中。
保留平时专题训练以及各类 Online Judge、算法比赛中完成的题目代码。
这些代码更多体现的是实际解题过程:
- 根据数据范围判断复杂度;
- 从题目中抽象算法模型;
- 选择合适的数据结构;
- 完成实现并处理边界情况;
- 对错误代码进行调试和修正。
随着题量增加,一些常见算法会逐渐形成自己熟悉的实现方式。相比直接复制一份所谓的"标准模板",我更希望通过反复使用,把算法实现真正变成自己的东西。
仓库中的代码主要使用 C++ 编写,并保留比较明显的算法竞赛风格。
竞赛代码通常更关注:
- 正确性;
- 时间复杂度和空间复杂度;
- 实现速度;
- 调试效率;
- 常用代码的复用。
因此,这里的代码不会刻意按照大型工程项目的方式进行封装。不同阶段的代码在命名、注释和写法上也可能存在差异,我会保留这些内容,因为它们本身也是学习过程的一部分。
长期做算法题对我最大的帮助,不只是记住了多少个算法。更重要的是逐渐形成下面几种能力:
- 问题建模:面对一道陌生题目,能够逐步判断它更接近图、树、区间、状态、字符串还是数学问题。
- 复杂度意识:根据数据范围判断某种算法是否可行,而不是先写完代码再考虑会不会超时。
- 代码实现:把一个抽象算法稳定地转化为 C++ 实现,并正确处理各种边界条件。
- 调试能力:能够根据 WA、TLE、MLE、RE 等结果快速排查思路、复杂度和代码实现中的问题。
这些能力也是我持续进行算法训练的主要原因。
这个仓库会继续用于保存后续完成的算法题和比赛代码。
我更希望它最终成为一份长期积累下来的算法学习记录,而不是一个为了展示而临时整理出来的题解合集。
刷题的意义,不是记住做过的题,而是提高解决下一道陌生问题的能力。
wangfuhong
主要方向:
- C++
- 算法与数据结构
- 算法竞赛
- Python
- 后端开发