数据结构与算法刷题攻略:两遍学习法与复习重写实战
发布时间:2026/10/10 18:59:03 锦皓数字建站

简介一份面向程序员求职与算法进阶的刷题全攻略资料包整合剑指Offer题解、程序员代码面试指南题解、九章算法讲解、牛客直通BAT算法课等经典内容同时收纳大公司笔试真题与LintCode编程题练习基本覆盖算法面试常见题型与解题思路。代码按学习阶段组织既保留第一遍学习时的原始实现也附带了两个月后复习时全部重新编写的版本通过两版对比可清晰看到思路演进和代码优化过程其中涉及动态规划、二叉树遍历、最大子矩形、分隔回文串等典型问题适合反复研读。资源共969个文件以468个Java源文件和493个编译生成的class文件为主辅以md、txt、docx说明文档及gitignore工程配置压缩包整体仅789KB轻量便携而目录结构清晰。目前已有41人学习下载可用于系统备战算法面试、快速回顾核心题型也适合温习后自测代码能力。1. 数据结构与算法刷题全攻略项目解压后别急着吃灰先把它拆成两遍学习计划“数据结构与算法刷题全攻略项目”这个名字在牛客、B站和GitHub上被反复搜因为它把校招和社招面试最常用的几套东西打成了一个包剑指Offer题解、程序员代码面试指南题解、九章算法讲解、牛客直通BAT算法课外加lintcode和大公司笔试真题。这些资源单看都不稀罕真正难的是怎么用起来。我见过太多人解压后拖进网盘吃灰也见过有人只抱着“第一遍学习代码”反复看完全不知道还有个“两个月后复习全部重新实现代码”的目录。这篇笔记就讲我实际跑通的用法第一遍怎么学复习重写怎么练笔试真题怎么排雷最后把刷题记录变成自己的面试弹药。2. 先搞清压缩包里有什么四套题源分工与两版本代码的目录组织2.1 从剑指Offer到牛客直通BAT四套题源怎么分工这类压缩包最忌讳一把抓。剑指Offer、程序员代码面试指南、九章算法、牛客直通BAT这四套资料覆盖的是不同层次的需求用错了顺序等于白刷。我一般这样拆剑指Offer题解适合第一遍打底。题目都是面试高频经典每道题都能讲清楚思路和边界拿来建立“见到题会套方法”的肌肉记忆最好。它的题解代码往往很短但隐藏了很多坑比如链表为空、数组越界、输入非法。程序员代码面试指南题解更偏算法设计题目比剑指Offer难一档很多题会考你“能不能把O(n^2)优化到O(n log n)”适合在剑指Offer过完一遍后再提升。九章算法讲解按专题组织二分、双指针、动规、图论分开讲。这不是拿来刷的是拿来查的。哪个专题薄弱就去补哪个比自己硬啃效率高得多。牛客直通BAT算法课和笔试真题其实是同一件事的两面。课程讲的是大厂笔试常用套路真题是真刀真枪的输入输出格式、数据规模和时限要求。这部分放到复习重写阶段做模拟最能暴露问题。这个项目名的卖点在于“第一遍学习代码”和“两个月后复习全部重新实现代码”是两套独立的文件。很多人没意识到这两套文件才是整个项目的核心。题解和课程只是输入你自己的两遍实现才是输出。所以解压后第一步不是打开题解而是看清楚目录结构别把两遍代码混在一处。2.2 第一遍学习代码与两个月后复习全部重新实现为什么留两版本我第一遍学的时候代码是带着注释的、照着题解思路写的可能还夹杂调试语句。两个月后这些代码基本忘了一半。这时候如果翻出旧代码看只会产生“我好像会了”的错觉。真正有效的做法是不打开旧代码只留题目列表从头重新实现一遍。两个版本放在一起对比才能看到自己哪里还记得、哪里真的忘了。这里有一个认知误区看你觉得自己记住了没用写出来才算。第一遍代码其实是“学习笔记”不是“答案库”。它记录的是我当时的思路、卡点、复杂度推演。两个月后重写代码则是把当时的思路在同一边界条件下再推演一遍能写通才算过。两版代码的差异就是学习的证据。所以目录里必须明确区分这两层。我会把第一遍代码放在first_round重写代码放review_rewrite两个目录之间不做任何软链接也不允许互相引用。哪怕同一道题完全不用改也要重新复制一份并写明“复习重写与第一次一致”这本身就是一次确认。2.3 代码目录怎么组织按公司、按标签、按时间三种方案整理目录时常见做法有三种按题源分、按算法标签分、按时间分。我最推荐的是“先按轮次再按题源最后按标签”三层。algorithm-prep/ ├── 01_first_round/ # 第一遍跟题解学思路 │ ├── jianzhi_offer/ │ │ ├── 03_数组中重复的数字.py │ │ ├── 04_二维数组中的查找.py │ │ └── 11_旋转数组的最小数字.py │ ├── jiu_zhang/ │ │ ├── two_pointers/ │ │ │ ├── 01_最长无重复子串.py │ │ │ └── 02_合并两个有序数组.py │ │ └── dp/ │ └── lintcode/ │ ├── 1xxx_xxx.py │ └── 2xxx_xxx.py ├── 02_review_rewrite/ # 两个月后关掉旧代码重写 │ ├── jianzhi_offer/ │ ├── programmer_code_guide/ │ └── company_exam_2025/ ├── 03_company_exam/ # 大公司笔试真题 │ ├── 某大厂笔试_2024_秋招/ │ └── 某大厂笔试_2025_春招/ ├── 04_notes/ # 错题笔记按标签记 │ ├── 排序算法/ │ └── 贪心/ └── README.md这个结构的好处是第一轮和第二轮不会互相污染。如果你按题源或按算法标签分第一遍和第二遍代码混在一起很难强迫自己不看旧代码。我在 README 里还会写清楚每个文件名的规则题目编号_题目名_方法名.py。方法名很重要比如双指针、快排、剪枝一眼就能知道这题考什么。命名定了之后搜索也省力。面试前想突击二分直接find review_rewrite -name *二分*把所有重写过的二分题拉出来再过一遍。这里我特别建议把README.md当作“刷题地图”上面写目前哪些专题过了一遍、哪些重写还没完成时刻知道自己的进度。3. 第一遍学习代码怎么用从看懂题解到写出来的闭环3.1 第一遍的关键是“想清楚”不是“写出来”第一遍接触新题最忌直接抄题解。我的流程是先看题目给五分钟自己推。五分钟推不出来再看题解的第一段思路描述不看代码。然后再自己白板写。这样写出来的代码就算和题解长得完全一样也经过了一次自己的思考。很多题看似是“不会”其实是“没见过套路”。比如剑指Offer里的旋转数组最小值第一次见可能懵但知道二分套上去之后后面再做类似题目就有方向了。第一遍就是建立套路库。做题时我会顺手把这道题的暴力解法和优化解法都写一遍。比如一道“两数之和”先写暴力枚举算法再把哈希或双指针写出来。这个过程能直观看到算法优化的收益而不是背结论。这也是为什么题解里明明给了最优解我还会先写暴力。暴力代码短逻辑直不容易错。写完暴力再跑样例确认理解题意了再去想怎么剪枝、怎么降复杂度。从暴力到剪枝的路径才是第一遍真正该学的。很多资料只给最终答案漏掉了“暴力为什么慢、剪枝怎么剪”的思考过程这套项目的九章算法和代码面试指南恰恰补上了这一步。3.2 用注释记录思路而不是粘贴答案第一遍学习的代码里注释比代码更重要。常见错误是题解里带什么注释就抄什么过一个月再看毫无记忆点。我自己的做法是按自己的话写注释只写三件事——思路切入点、关键边界、复杂度。# 二分查找模板查找有序数组中第一个 target 的位置 # 思路维护 [left, right] 区间mid 满足条件就收缩右侧 # 注意终止条件是 left right 而不是 left right # 边界数组为空直接返回 0target 比所有值大都返回 len(nums) def lower_bound(nums, target): left, right 0, len(nums) # 右开区间方便处理未找到的情况 while left right: mid left (right - left) // 2 # 防止 leftright 溢出 if nums[mid] target: left mid 1 else: right mid return left这段代码的注释不是题解原话而是我自己的理解。“右开区间”和“终止条件”是我当初写错两次的地方必须重点标出来。left (right - left) // 2是处理整型溢出的通用写法在 C 里尤其重要Python 里也养成习惯。第一遍学习的每个文件都应该包含这样的注释。等到两个月后重写我要求自己先写注释、再写代码因为注释能检验我是不是真的理解了如果注释写不出来说明思路根本没建立。这比白板题还严格。3.3 一道题跑通后必须做的三件事很多人刷题是“提交通过结束”。我后来改成“通过三步”刷题量虽然少了但记住的时间长了很多。第一步写测试用例。剑指Offer的题目都有例子但远远不够。我会补空输入、单元素输入、全重复输入、最大输入把边界都跑一遍。比如链表题一定会测试头结点被删除的情况。第二步算复杂度。不只看题解写的结论而是自己把循环数一遍写清空间用了几个临时变量。第三步和题解对比。我的实现可能通过但可能代码冗余、可读性差。打开题解看它怎么精简把差异点记下来。这三件事都不难但很容易偷懒。我做过统计直接刷题不记笔记两周后能复现的题不到三成做了这三步的题两个月后重写时大部分能独立做出来。这也是为什么这个攻略项目把“复习重写代码”单独列出来——它就是给这三步做验收的。4. 两个月后复习重写重新实现代码的正确姿势4.1 复习重写不是背答案先看题、再写、最后对比两个月后重新实现最容易踩的坑是“凭记忆抄旧代码”。大脑会对见过的东西产生熟悉感看到题目就想翻旧代码。我应对的办法是物理隔离重写时把旧代码目录整个折叠编辑器里只打开题目列表绝对不看旧文件。如果一道题真的卡死超过三十分钟宁可标记“重写失败”也不要看旧代码。看一次旧代码这次重写就废了。重写时我会给自己限时。单题不超40分钟其中前20分钟用来想思路后20分钟写代码和自测。这样做是为了模拟笔试的紧张感。笔试真题里一道编程题平均也就四十分钟所以平时就该用这个节奏练。4.2 重写代码时怎么控制时间与边界重写阶段最重要的是“卡时间”。我手机开倒计时四十分钟到不管写没写完都要停。这样做的原因是真实笔试时你不可能无限时而且笔试常见问题不是不会做是会在某道题上死磕导致后面简单题没时间写。把限时训练练成习惯笔试心态会稳很多。边界条件第二次写时依然容易漏我列了一个自查清单每个文件开头写好待确认边界# 边界自查 # 1. 输入为空 / 长度为0 # 2. 长度1 # 3. 全部元素相等 # 4. 最大值/最小值int溢出或超大数组 # 5. 目标不存在/超过范围这个清单不是每次都要逐条写但它能提醒我在重写时不要只顾主路径。比如排序算法里归并排序很容易在递归合并时把索引写错二分查找很容易在left mid 1还是left mid上翻车。重写时我会刻意在核心循环处加断言比如assert 0 mid len(nums)assert不能用于线上提交但在本地自测时非常管用能立刻暴露索引越界或死循环的问题。笔试提交前我会删掉所有断言。4.3 用diff和测试用例校验两版代码的差异重写完成后对比两版代码是最有价值的一步。我不用肉眼一行行对比而是用命令行工具diff -u 01_first_round/jianzhi_offer/11_旋转数组的最小数字.py 02_review_rewrite/jianzhi_offer/11_旋转数组的最小数字.pydiff会输出两个文件的差异。如果是空输出说明两次实现完全一致这通常意味着我第一次学的思路还完整在脑子里。如果差异很大我需要判断是重写实现更简洁了还是把原来的正确版本改错了。我还会把两个版本都跑一遍同一组测试用例用结果说话。python3 01_first_round/jianzhi_offer/11_旋转数组的最小数字.py python3 02_review_rewrite/jianzhi_offer/11_旋转数组的最小数字.py如果两个输出相同说明行为等价。如果不同就把重写版的输出贴到自己的笔记里标注“和第一版不一致原因待查”。这一步常常能发现第一个版本里隐藏的 bug也算意外收获。5. 大公司笔试真题与lintcode刷题避坑与常见排查5.1 笔试真题和面试题的区别数据规模、输入输出、时空限制很多人在剑指Offer和lintcode上刷得飞起一到公司笔试题却挂原因就是没分清笔试和面试的区别。面试题通常让你写核心函数输入已经帮你处理好了笔试真题要求你从标准输入读取按格式输出处理多组用例并且在严格的时间限制下运行。比如 lintcode 上的题大多已经帮你封装好函数签名你只要实现def solution(nums, target)就行。但大公司笔试真题往往是“读一个数组再读一个整数输出两行结果”输入里的空格、换行、EOF都可能坑你。我在笔试真题目录里专门放了一个input_template.py用来应对常见输入格式import sys def main(): data sys.stdin.read().strip().split() if not data: return idx 0 n int(data[idx]); idx 1 nums list(map(int, data[idx:idxn])); idx n target int(data[idx]) print(solve(nums, target)) if __name__ __main__: main()sys.stdin.read()一次性读取全部输入适用于大多数在线评测系统。.strip().split()能处理行尾空格和空行比input()循环不容易出错。笔试时最怕输入解析出问题这个模板我每次笔试前都会复制一份。5.2 避坑三个让刷题翻车的常见问题我在这套攻略上摔过三个大跟头每条都值得单独说。第一个看题解时觉得全懂了关掉题解写不出来。现象是“看懂”和“写出”的鸿沟。原因在于第一遍学习时主动思考太少大部分时间花在被题解牵着走。解决方法是刷题时强制自己先写注释再写代码注释写不出就不允许开 IDE。这个方法笨但有效。第二个复习重写时忍不住翻旧代码。现象是我一开始把两个版本放在同一个目录写不出时就 fzf 搜题目结果瞄到旧代码思路一下被带偏。原因是对“复习重写”的规则不够硬。解决方法是把first_round目录改成只读权限或放到另外的 git 分支。没有强制的物理隔离重写大概率变成抄写。第三个刷题量上去了笔试还是挂。现象是平时刷题每题都能过但笔试时经常编译不过、超时或者卡输入。原因是平时只用了 IDE没在真正的在线评测环境里跑过也没严格卡时间。解决方法是每周至少做两场完整的牛客或 lintcode 模拟把输入输出模板、时间盒都当成正式笔试来执行。5.3 从题解到代码怎么识别“假题解”与“真可跑”这套项目压缩包里既然有题解就免不了混入一些假题解。什么叫假题解只有思路、没有完整代码代码只有函数体、没有输入输出处理代码有严重 bug跑不了样例。我识别假题解有三个标准第一看复杂度分析如果题解没写时间复杂度或空间复杂度多半是从哪抄来的一句话代码不值得信。第二看边界处理一个可靠的题解必然会讨论空输入、单元素、重复元素。第三实际跑一遍。我不会在本地随便跑而是把代码粘到 lintcode 对应题目的编辑器里提交一次。能过才说这道题“会了”不过就按失败处理继续重写。这个习惯让我排掉了很多看着很有道理、实际跑不通的样例代码。6. 把刷题记录变成自己的面试弹药库三个进阶技巧这套攻略用完整一遍后最大的资产不是题解而是自己写的两版代码和错题笔记。面试前我复习的顺序是先翻04_notes里的错题再挑02_review_rewrite里的题动手重写最后用03_company_exam里的真题做模拟。但光这样还不够我后来加了三个进阶动作让刷题记录真正变成面试时的“弹药库”。第一个动作是为每道重点题写“面试讲解稿”。面试官让你讲题时不是只讲代码而是讲思路。我在每个重写文件末尾加了一段注释模拟向别人解释的样子先说什么场景再说什么解法最后说为什么不是暴力。这段文字不提交给在线评测但面试前过一遍会非常稳。第二个动作是给同一道题维护“多解法表”。剑指Offer里很多题都有暴力、优化、特殊技巧三种解法面试时先说暴力再优化展示思维深度。第三个动作是定时清理笔记把已经稳定掌握的题移出重点区只保留反复出错的。我面试前一周就只盯这些错题。有一次我面试被问到一个堆排序算法的变体正好是我两个月前重写过的原题但第一次实现时堆的调整方向写反了。好在我重写时单独标记了“易错点”并写了讲解稿现场才没翻车。这让我更确信刷题攻略的价值不在于收集而在于你拿它做了什么。希望这套“两遍写法”对你有用。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。