
简介面向国际大学生程序设计竞赛ACM/ICPC选手、算法学习者和求职面试者这份《算法300题题目大全PDF》整理自芬兰CSES题库汇集了大量高质量算法题目可解决因网络限制无法直接访问CSES官网的离线刷题需求。PDF共收录约三百道题目覆盖数据结构、排序、搜索、图论、动态规划、贪心策略等核心算法方向每道题均包含清晰的问题描述、输入输出格式和样例测试用例同时配合虚拟评测平台和题解代码仓库便于提交代码、对比思路和查漏补缺。这些题目既强调基础算法的理解也注重综合运用与代码实现能力适合按专题逐步突破。资源打包为一个PDF文件压缩包大小约三十一点四三兆字节轻量易存适合日常翻阅或备赛冲刺。目前已有二百五十二人学习下载是备战程序设计竞赛和技术面试时值得常备的刷题合集。1. 算法 300 题题目大全 PDF刷题前先想清楚这四件事秋招前两周我收到转发来的《算法 300 题 题目大全 PDF》封面写着涵盖 LeetCode 高频题和数据结构与算法基础大小有几十兆。当时只干了一件事按文件名排序从第一题开始做。结果三天后停在了第 40 题——前面是双指针后面突然蹦出平衡树没有分类、没有难度标记、没有题解入口做一道查一道进度像爬坡。后来换了思路把这 300 题当成一份题目索引而不是题解书先盘目录、再分专题、只挑高频区间刷完前 120 题面试里遇到的排序、KMP、动态规划基本都踩过。这篇就按这个思路展开PDF 值不值得用、怎么辨识质量、怎么把纸质目录变成可执行的刷题计划以及最常踩的五个坑。适合准备算法面试的开发者、转算法岗的学生也适合带新人的老工程师。2. 拆开 300 题先盘目录再分专题最后排优先级2.1 拿到 PDF 的第一件事不是做题是盘目录一份“题目大全”类 PDF通常包含三种东西题目列表、参考代码、复杂度讲解。比例不同价值差很远。我拿到后先做三件事翻目录页数、看题目标注、抽看三道题的解法和用例。常见做法是看它有没有标注题源。一份正经的算法 300 题 PDF应该能看出题目来自 LeetCode、剑指 Offer、王道数据结构或 POJ因为不同题源考察侧重点不一样。LeetCode 的题偏工程面试场景剑指 Offer 的题偏基础实现细节POJ 偏竞赛思维——如果一份 PDF 全部混在一起且不标注出处刷题时容易误判难度。抽看解法更重要。翻到目录列出的第 100 题左右看它给出的参考代码是否完整、是否带复杂度分析。只有代码没有分析说明它的定位是“背答案用”有代码有复杂度有边界情况讨论才是能用来学习的材料。我见过不少“算法 300 题”PDF 其实是网上题目汇总的粗暴转存代码缺缩进、变量名乱、没有测试用例——这种只配当题目清单用。2.2 按专题把 300 题重新归堆拿到 PDF 之后我先按自己的分类把 300 题重新归堆不按原目录顺序刷。分类维度就六类数组与双指针、链表、树与图、动态规划与贪心、字符串与 KMP、排序与查找。这个顺序也是我在实际面试里被考察频次的倒序动态规划和树永远是重头。怎么把 PDF 里的题目映射到这些专题看题目的核心解题思路不看题目描述表面。比如“最长回文子串”归字符串而不是数组“合并区间”归排序而不是数组“二叉树最近公共祖先”归树与图。这个归类过程本身就是第一轮学习——它逼着你看清每道题到底在考哪个知识点。归堆之后我会给每道题标一个“专题内序号”和“难度估分”难度估分按 1 到 3 打1 是能独立写出裸题2 是能写出主要逻辑但边界易错3 是看了题解才能写完整。这个估分直接决定后续二刷三刷的优先级。2.3 专题权重表与刷题顺序参考专题常见题量300 题中预估面试出现频率建议刷题顺序数组与双指针、滑动窗口60–70 题极高第 1 批排序与查找快排、归并、二分40–50 题极高第 1 批链表含快慢指针、反转、合并30–40 题高第 2 批树与图遍历、BFS、DFS、回溯70–80 题很高第 2 批字符串与 KMP、模式匹配30–40 题中第 3 批动态规划与贪心60–70 题很高第 3 批提示上表的题量分布是我按常见“算法 300 题”类 PDF 内容估的实际以你手头文件为准。但顺序的参考价值不大变—先刷双指针和排序建立手感再进链表和树最后啃动态规划。因为动态规划的题很多依赖前几个专题的代码基础比如用排序预处理、用递归遍历树结构。刷题顺序里有个前人踩出来的原则每个专题内的题按难度从 1 到 3 排先把该专题内所有 1 分题做完再做 2 分题3 分题留到第二轮。这样能避免“一上来死在最长上升子序列然后放弃整个动态规划”的翻车。2.4 用脚本快速统计 PDF 的专题分布手动归堆 300 题很累我一般会写一个 Python 脚本先把 PDF 导出的目录文本拉出来做初步归类。下面是实际用过的脚本针对“从 PDF 复制出来的纯文本目录”做关键词匹配统计import re from collections import Counter # 假设已经从PDF中把目录复制到 catalog.txt # 每行格式类似第37题 合并K个升序链表 或 37. Longest Substring Without Repeating Characters with open(catalog.txt, r, encodingutf-8) as f: lines f.readlines() pattern re.compile(r^(?:第?\s*(\d)\s*题|[0-9][\.\)、])\s*(.*)$, re.IGNORECASE) # 关键词到专题的映射 tags { 数组/双指针: [two sum, 双指针, 滑动窗口, 合并区间, 数组], 链表: [链表, linked list, 反转链表, 环], 树/图: [二叉, 树的, bfs, dfs, 岛屿, 二叉树, 图], 动态规划: [动态规划, dp, 背包, 子序列, 最长], 字符串: [kmp, 字符串, 回文, 子串], 排序/查找: [排序, 二分, 快排, 归并, 堆排序, 查找], } buckets Counter() for line in lines: line line.strip() m pattern.match(line) if not m: buckets[无法识别] 1 continue title m.group(2).strip().lower() matched False for tag, keys in tags.items(): if any(k in title for k in keys): buckets[tag] 1 matched True break if not matched: buckets[其他] 1 for tag, count in buckets.most_common(): print(f{tag}: {count} 题)这段脚本的逻辑不复杂先用正则匹配每行的题号和题目名再对题目名做小写化处理按关键词表命中专题命不中的进“其他”桶。输出统计后你可以根据自己 PDF 的实际内容扩展tags字典里的关键词——比如 A* 算法归“树/图”、哈希表归“数组/双指针”、位运算单独开一个桶。正则里的^和[0-9][\.\)、]是为了兼容“37.”、“第37题”、“37、”三种常见目录写法如果你的目录是37_merge_k_sorted_lists这种带下划线的要把正则改成匹配下划线。这个脚本输出后对照我上面的权重表就能快速判断这份 300 题偏科不偏科——如果“树/图”只有 20 题而“排序”有 60 题基本说明这份题集来自某个竞赛资料不适合面试刷。3. 把 PDF 变成刷题系统一题一卡加最小评测环境3.1 题卡模板读题、思路、复杂度、复盘四个字段盲目一道道往下做是刷题失败的元凶。我带的实习生用我给的模板三个月刷完核心题面试手写题基本一次过。这个模板的核心是一题一卡每道题建一条 Markdown 记录字段固定为题目编号、专题、难度估分、我的思路、参考思路、复杂度、代码要点、踩坑记录、下次复习日期。## 题号: 37 合并K个升序链表 - 专题: 链表 / 堆 - 难度估分: 2 - 我的思路: 两两合并每轮合并两个链表 - 参考思路: 用优先队列维护K个头节点每次取最小O(n log k) - 复杂度: 队列法 O(n log k) / 两两合并 O(n k) - 代码要点: 优先队列要自定义比较器注意空链表 - 踩坑: Python heapq 不能直接比较 ListNode需要包一层 (val, idx, node) - 复习日期: 2026-03-20字段里的“复习日期”是二刷的调度依据按 1、3、7、14 天的间隔设置。每次打开题卡先看“我的思路”和“参考思路”是否一致不一致才需要重做。这道题的代码我不会放进题卡而是单独放一个按专题组织的代码目录因为题卡里放代码会让人忍不住抄。为什么“踩坑记录”必填因为 300 题的题量决定了你不可能记住每道题的细节但人会记住自己犯过的错。比如上面那条“Python heapq 不能直接比较 ListNode”下次遇到“合并K个链表”就会先想到包一层索引元组不用重新调试。3.2 最小评测环境一道题的完整落地代码与跑测方法题卡只是记录真正练手还是要在本地写代码。我不建议上来就开在线评测系统刷 300 题因为 PDF 里的题很多是原题或改编题本地搭一个最小评测环境就够用。下面是一个覆盖本题卡场景的最小 Python 测试模板支持断言、随机数据和耗时时长统计import heapq import time from typing import List, Optional class ListNode: def __init__(self, val0, nextNone): self.val val self.next next def merge_k_lists(lists: List[Optional[ListNode]]) - Optional[ListNode]: # 参考解法优先队列维护每个链表的当前头 dummy ListNode() tail dummy heap [] for i, node in enumerate(lists): if node: # 包索引避免直接比较 ListNode heapq.heappush(heap, (node.val, i, node)) while heap: val, i, node heapq.heappop(heap) tail.next node tail tail.next if node.next: heapq.heappush(heap, (node.next.val, i, node.next)) return dummy.next def list_to_nodes(arr): dummy ListNode() tail dummy for v in arr: tail.next ListNode(v) tail tail.next return dummy.next # 测试用例 test_cases [ ([[1,4,5],[1,3,4],[2,6]], [1,1,2,3,4,4,5,6]), ([], None), ([[]], None), ] for i, (lists, expected) in enumerate(test_cases): ll [list_to_nodes(x) for x in lists] t0 time.perf_counter() result merge_k_lists(ll) cost (time.perf_counter() - t0) * 1000 if expected is None: assert result is None, fcase {i} failed: expected None else: arr [] while result: arr.append(result.val) result result.next assert arr expected, fcase {i} failed: got {arr}, want {expected} print(fcase {i} ok, cost{cost:.2f}ms)跑这个脚本的两个参数值得说明heapq.heappush传入(val, i, node)时第三位传 node 而不是链表值是因为堆比较时会先比 val 再比索引node 永远不会参与比较避开了“ListNode 不能比较”的坑time.perf_counter()测出的耗时是单次调用的但当链表数据量增大时这个数字能帮你验证是 O(n log k) 还是 O(n k)——如果你把两两合并的实现也跑一遍对比数据会非常直观。3.3 三轮刷题法先广后深300 题不可能一轮刷完也不该一轮刷完。我一般排三轮第一轮广度按专题顺序只做 1 分题和部分 2 分题目标是全覆盖所有高频考点。每道题限时 30 分钟超时直接看题解记录思路差异后继续下一道。第一轮结束时六个专题都过了一遍面试时至少能说出“这题考什么、方向是什么”。第二轮深度回头做 2 分题和第一轮标记过“我有想法但没写对”的题重点看代码实现细节和边界情况。这一轮不追求数量一天两道就够。第三轮复习只刷复习日期到期的题卡和全部 3 分题主线是维持手感。注意第一轮千万别做 3 分题。动态规划里的“编辑距离”、树里的“莫里斯遍历”这类题第一轮做只会打击信心而且半小时根本不够。把 3 分题留到第二轮以后那时候你已经见过至少 100 道题思路库有了才有可能解出来。4. 刷算法 300 题最容易翻车的 5 个地方4.1 只做题不总结刷到 200 题时前 100 题全忘光现象一个月刷了 150 题随机抽 20 道做过的题有 12 道想不起来思路5 道连题目含义都记不清。原因刷题时只顾着“AC 了没”没建立题与题之间的联系记忆没有锚点。解决严格执行题卡模板每题必填“我的思路”和“参考思路”两个字段并且强制写一句“这题和之前哪题相似”。比如“合并K个升序链表”和“排序一个链表”共用“拆解后合并”的思路框架写上关联两题互相成为记忆锚点。4.2 把 PDF 当答案书抄代码没调试现象对着 PDF 里的参考代码一行行敲敲完觉得“明白了”关上编辑器全忘。原因抄代码是视觉输入不是解题训练参考代码里真正有价值的复杂度边界和数据结构选择完全没进脑子。解决把 PDF 里的参考代码当成评审对象——先用自己的思路写一遍再打开 PDF 对照差异然后把差异整理成题卡里的“代码要点”字段。抄可以抄完必须立刻关掉文档完整重写一遍第一次重写卡住的地方就是你的真实盲点。4.3 死磕难题一周卡在一道题上现象一道三维动态规划题看了三天题解每天两小时最后也没完全搞懂。原因300 题内容的覆盖面远大于单题深度你在一道题上花的 6 小时够刷完整个“数组/双指针”专题里的 10 道 1 分题。解决设 30 分钟硬上限超时直接看题解把“卡在哪一步”记入题卡。这道题进入第二轮列表一周后带着“上次卡在状态定义”的预期再试。坚持这个规则的副作用很神奇很多难题第一次没懂两周后回来再看常看常新。4.4 忽略复杂度分析只求跑通现象解法写出来了测试也过了但面试官一追问时间复杂度就卡壳。这是刷算法题库最典型的“假熟练”现象。原因PDF 里的参考题解往往只给一种解法没有给出不同解法的复杂度对比导致你以为“能跑就对”。解决每道题在题卡里写两个复杂度我的解法和参考解法各自的复杂度并注明差异来源。比如“合并K个链表”两两合并是 O(nk)优先队列是 O(n log k)数据量上到 10^5 时跑题是必然。养成写复杂度习惯后面试手写环节会自然说出“这里用优先队列因为 log k 比 k 好”这就是面试官要的信号。4.5 不做复习调度二刷三刷全是新题现象第一轮刷完第二轮从第 1 题重新开始发现 80% 还是不会。原因没有按遗忘曲线安排复习所有知识一次性垒进去时间一长全部风化。解决用题卡里的“复习日期”字段按 1、3、7、14 天做回扫。回扫时只做两件事一是看“参考思路”能不能自己复述出来二是把代码删掉重写不看参考。复习日期到期的题如果能在 5 分钟内写出核心逻辑就把它标记为“已掌握”后续复习不再回看。这样第二轮的“新题”会越来越少第三轮只碰漏网之鱼。5. 别急着删 PDF把目录反向变成你的知识图谱与错题回扫工具5.1 用题目目录反向画知识依赖图大部分算法 300 题 PDF 的问题是“平铺”——没有标注题目之间的依赖关系。但依赖是真实存在的二分查找依赖有序数组的认知归并排序依赖递归和合并有序链表的操作KMP 依赖前缀函数的理解。我二刷完会自己整理一张“前置依赖”清单把每个专题里“不会这个知识点就没法做下一题”的题挑出来比如“链表反转”是所有链表合并类题目的前置“树的遍历框架”是回溯和 BFS 的前置。前置知识依赖它的后续题类型链表反转回文链表、反转区间、K 个一组翻转二叉树的三种遍历框架最大深度、最近公共祖先、路径总和快速排序 partition数组第 K 大、颜色分类、最小未排序区间KMP 前缀函数重复子串、最短回文串、字符串匹配这张表就是你的知识图谱。面试时遇到没见过的题先判断它属于哪个前置体系再套用对应框架。实际面试里“数组第 K 大”这道题就是快排 partition 的直接变形画不出依赖图的面试者会去用堆能画出依赖图的会先想 partition 然后写期望 O(n) 的算法——高下立判。5.2 错题回扫脚本用文件状态自动安排复习题卡里的“复习日期”如果手动维护坚持两周就会断。我用一个小脚本读题卡的 Markdown 文件自动算今天该复习哪些题核心逻辑是这样的import json import datetime # cards.json 格式: # [{title: 合并K个升序链表, review_date: 2026-03-20, mastered: false}] with open(cards.json, r, encodingutf-8) as f: cards json.load(f) today datetime.date.today() due [c for c in cards if not c[mastered] and (today - datetime.date.fromisoformat(c[review_date])).days 0] if not due: print(今天没有到期题可推进新题) else: for c in sorted(due, keylambda x: x[review_date]): print(f[应复习] {c[title]}计划日期 {c[review_date]}) # 顺手输出三天内将到期提前安排 soon [c for c in cards if not c[mastered] and 0 (datetime.date.fromisoformat(c[review_date]) - today).days 3] if soon: print(--- 三天内到期 ---) for c in soon: print(f[即将] {c[title]}{c[review_date]})这个脚本的说明用date.fromisoformat把字符串日期转成日期对象再和今天做差“三天内到期”的逻辑是提前预警避免被动mastered字段对应上一章的“已掌握”标记标记后不再进回扫列表。脚本输出后我会把到期的题卡全部打开先做“复述思路”再做“删代码重写”最后批量更新review_date和下一条计划。整个流程十分钟左右代价小所以能坚持。5.3 将题目难度与真实面试题对齐最后一条是血泪经验。刷完 300 题不代表面试稳过因为 PDF 里的题和面试官现场出的题存在“提示差”——面试题会要求你现场口述复杂度和边界PDF 题不会。我二刷时会在题卡里补一个“面试追问”字段比如“这题如果链表有环怎么办”“数组有序和乱序的区别是什么”“内存有限怎么处理海量输入”用来模拟面试现场被追着问的状态。这样把题卡从刷题记录升级成模拟面试题库300 题才真正变成了你的求职资产。我现在还保留着最初那份 PDF但已经没有翻它了——取而代之的是自己生成的 200 多张题卡、一张专题依赖表和一段几十行的回扫脚本。这是我认为“算法 300 题大全 PDF”最理想的打开方式把它当成起点而不是终点。希望这篇能帮到你也祝你把题目换成自己的体系。本文还有配套的精品资源点击获取