尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
数据结构与算法刷题全攻略:两遍刷题法真正掌握笔试算法
简介面向备战大厂算法面试的求职者与在校生这份压缩包是一份体系化的数据结构与算法刷题代码合集覆盖剑指Offer题解、程序员代码面试指南、九章算法、牛客直通BAT课程及lintcode/大公司笔试真题编程题。资源同时收录第一遍学习代码和两个月后复习重新实现的全套代码便于对照同一题目的多次解题思路链表、二叉树、动态规划等经典考点均有涉及。包内共969个文件以468个Java源文件与493个class编译文件为主配合md/txt/docx说明文档及gitignore工程文件可直接在IDE中运行、编译并对照验证。压缩包约789KB轻量但模块划分清晰。已有40人学习下载适合用来进行面试前集中刷题、专项复习与解题思路沉淀。1. 这个“数据结构与算法刷题全攻略”到底值不值得啃先看包里的三层材料先说结论这个项目最值钱的不是剑指Offer题解也不是牛客直通BAT算法课的录播笔记而是那个“第一遍学习代码”和“两个月后复习全部重新实现代码”的对照动作。数据结构与算法刷题全攻略这类资源网上很多但大多数人只做了第一遍看完题解就以为自己会了结果笔试现场翻车。这个压缩包的价值在于它把“学”和“验”拆成了两个阶段逼着你两个月后再写一遍这一遍才是真正把题解变成自己能力的过程。适合三类人准备大厂笔试的应届生、要跳槽但算法基础薄弱的在职开发、以及刷题刷到一半坚持不下来的半途选手。如果你是刚学完数据结构、连链表反转都要想半天的状态这份材料也能用但需要自己补一步基础语法。2. 从刷题第一遍到两个月后重写把剑指Offer和牛客课的题单串成一条线2.1 剑指Offer题解为什么它是第一遍的基准盘剑指Offer这六十多道题被大厂笔试反复引用了几轮它的题面短、边界条件密集几乎每一道都能延伸出一个笔试变种。我一般建议第一遍不要按书里的章节顺序刷而是按题型重排数组、链表、树、字符串、动态规划五类。原因是剑指Offer的题目难度不是线性递增的按书刷容易在树和DP阶段劝退。以“树的遍历”为例剑指Offer里有重建二叉树、树的子结构、镜像二叉树、层次打印等六七道题。放在一起刷你会在三天内把前序中序后序、递归和非递归写法全部过一遍这种集中轰炸的效果远好于隔几天碰一道。题解的价值在于它给的是“最小可复现”的解法不是最优解。很多人读完觉得“就这太简单了”其实漏了考点。比如反转链表这道题题解给的往往是三指针迭代法但这道题真正的考察点不只是迭代还有递归写法能不能在两分钟内写对。刷第一遍的时候每道题都要做两遍先按题解思路默写一遍再试着自己推递归版本。这个习惯比刷题数量重要得多。2.2 牛客直通BAT课与九章算法讲解课和题怎么配着用牛客直通BAT这套课本质上是把大厂笔试题按公司维度做了归类而九章算法讲解是按算法范式做的归类。两套课的维度不同很多人只看一套这是个漏。正确的用法是第一遍以九章的算法分类为主线配合剑指Offer题解验证第二遍以牛客的公司真题为主线用来摸底自己离目标公司的差距。我见过不少人是这样翻车的先看九章的DP讲义觉得听懂了然后直接去做牛客的高频题结果做不出来回头又去看讲义陷入“听课—看不懂—再听课”的循环。问题不出在课出在中间少了一层剑指Offer的过渡。对应关系大概是第一周数组、链表、字符串基础配合剑指Offer对应章节 第二周树、栈、队列、双端队列配合牛客BAT课的树章节 第三周排序与二分这里的归并排序算法和快排必须手写过关 第四周动态规划、贪心、回溯这一周要放慢节奏不可贪多这样安排下来九章讲的抽象模型落在了剑指Offer的具体题目上牛客真题又验证了掌握程度三层材料各司其职。2.3 两个月后重新实现把“看懂的代码”变成“自己的代码”标题里“两个月后复习全部重新实现代码”这个动作很多刷题的人都不会做但它恰恰是检验真懂的唯一标准。人类记忆的遗忘曲线很残酷第一遍刷完的题两周后能独立写出来的不到四成。两个月后如果还能保持七八成以上的复现率说明你确实建立了自己的解题框架而不是在背答案。我自己的做法是第一遍刷的时候在每道题的代码文件头部写一个两行的思路注释。两个月后复习时先把注释盖住自己推一遍思路再写代码。如果推不出来才允许看注释。如果注释也看不懂说明第一遍就没真懂这道题需要标记为“重刷”而不是“复习”。这个“重写代码”的过程会暴露一个特别常见的问题你当时能照着题解写出来是因为题解把中间的空跳过了。比如快速排序的partition边界条件第一遍照着写不会出错但自己重写的时候递归退化的边界、等于pivot的元素放左边还是右边这些细节全都会冒出来。所以复习时重写类似于工作里的code review不是抄一遍而是找出自己当时的理解盲区。3. 用最小环境跑通刷题代码目录结构、对拍脚本与两段必手写算法3.1 建立按题型分组的目录结构别把题号当文件夹刷题代码的目录管理是个被严重低估的环节。很多人把代码放在“一行一个文件”的文件夹里文件名是offer_03.py、offer_04.py两个月后想找一道题得翻半天。我见过比较实用的目录组织方式是按算法范式分组再在里面按题目编号命名。algorithm-daily/ ├── array/ │ ├── offer_03_duplicate.py │ ├── offer_04_matrix_search.py │ └── ... ├── linked_list/ │ ├── offer_24_reverse.py │ └── ... ├── tree/ │ ├── offer_07_rebuild.py │ └── ... ├── dp/ │ ├── offer_10_fib.py │ └── ... ├── string/ │ ├── offer_05_replace_space.py │ └── ... └── cases/ ├── 001.in ├── 001.out └── ...这样做的逻辑是复习的时候你不会记得题号但你会记得“我当时刷过一道树的层次遍历题”按题型目录去找效率会高很多。cases 目录存放的是自己造的测试用例配合对拍脚本使用不要手动验证输出。3.2 一个最小测试脚本用命令行把答案和期望值对拍刷题不能“看完了觉得对就算对”必须跑起来。大部分OJ平台提交后只告诉你“通过/不通过”但本地调试时的信息远远不够。我写了一个很小的对拍脚本放在项目根目录下用来做本地批量验证。# judge.py 用法: python judge.py solution.py case_id import importlib.util import sys import time from pathlib import Path def load_solution(path): # 从指定路径动态加载题解文件 spec importlib.util.spec_from_file_location(sol, path) mod importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod def run_case(sol, case_id, cases_dircases): # 约定: case_id 对应的输入和期望输出都在 cases 目录下 in_path Path(cases_dir) / f{case_id}.in out_path Path(cases_dir) / f{case_id}.out data in_path.read_text().strip().splitlines() expect out_path.read_text().strip() t0 time.time() got sol.solve(data) # 约定题解文件必须暴露 solve(data) 入口 cost_ms (time.time() - t0) * 1000 if str(got).strip() expect: print(fcase {case_id}: PASS ({cost_ms:.1f}ms)) else: print(fcase {case_id}: FAIL, got{got}, expect{expect}) if __name__ __main__: sol_path, cid sys.argv[1], sys.argv[2] run_case(load_solution(sol_path), cid)这个脚本的核心约定是每题解文件必须暴露一个solve(data)函数data是从.in文件按行读取的列表返回值会被和.out文件逐字符比较。逻辑上很简单但它解决了两个问题一是用例可以反复跑二是能统计耗时让你直观地感受到暴力枚举和优化算法之间的时间差。这里的参数设置需要注意cases目录下的文件名必须是001.in和001.out这种严格对应关系否则脚本会读不到文件。题解入口统一暴露solve这样不同题目的代码格式一致批处理时不需要改脚本。如果你习惯让入口接受参数而不是读文件也可以改成sol.solve(rows)但整套项目的约定要保持一致。3.3 归并排序与KMP两段必须手写的对照代码排序和字符串匹配是笔试里出现频率最高的两块内容。归并排序是“分治思想”的典型代表它的递归写法和非递归写法也就是自底向上的归并至少要有一版能直接手写。KMP则是字符串题的分水岭会写KMP的人和不写KMP的人在笔试中的表现会差一个档次。归并排序的递归实现def merge_sort(arr): # 递归终止条件数组只剩一个元素时天然有序 if len(arr) 1: return arr mid len(arr) // 2 # 分治先排左半再排右半 left merge_sort(arr[:mid]) right merge_sort(arr[mid:]) # 合并两个有序数组是核心操作 return merge(left, right) def merge(a, b): res [] i j 0 while i len(a) and j len(b): if a[i] b[j]: # 等于时取左边保持排序稳定性 res.append(a[i]) i 1 else: res.append(b[j]) j 1 # 剩余部分直接接在末尾 res.extend(a[i:]) res.extend(b[j:]) return res逻辑说明merge_sort把问题拆成两半各自递归解决后合并。merge是稳定合并比较时用而不是这样相等元素的相对顺序不会被打乱。笔试中常见的要求是“排序后保持原顺序”这个细节会被考到。参数说明arr[:mid]这种切片写法简单直观但每层递归都会产生新数组空间复杂度是O(n log n)。如果你想在真实笔试环境中写空间复杂度更优的版本应该用索引下标加辅助数组的方式也就是原地归并。笔试如果明确说了内存受限用切片版会超空间这是踩坑点。KMP的主函数和 next 数组构建def get_next(p): n len(p) nxt [-1] * n i, j 0, -1 while i n - 1: if j -1 or p[i] p[j]: i 1 j 1 # KMP优化的一步跳过必然失配的回退位置 if p[i] ! p[j]: nxt[i] j else: nxt[i] nxt[j] else: j nxt[j] return nxt def kmp_match(s, p): nxt get_next(p) i j 0 while i len(s) and j len(p): if j -1 or s[i] p[j]: i 1 j 1 else: j nxt[j] if j len(p): return i - j # 返回匹配起始下标 return -1逻辑说明get_next里j代表前缀匹配长度nxt[i]记录的是p[:i]串的最长相等前后缀长度。注意第一行nxt [-1] * n这里-1是一个哨兵值表示“回到了开头”能避免在循环里写额外的边界判断。KMP匹配阶段失配时模式串指针通过nxt[j]回退主串指针i不回退所以整体复杂度是O(m n)。参数说明当模式串长度为n时nxt数组的长度是n第一个元素固定为-1。如果你在OJ上遇到“KMP匹配超时”九成问题出在get_next的实现上——没有做p[i] ! p[j]这个优化会导致失配时回退过多。另一个常见问题是返回的下标从0开始还是从1开始这在笔试题目里经常不明确说建议刷题时统一按“下标从0开始”来假设。4. 刷题节奏的三个关键参数21天周期、难度梯度、复盘粒度怎么定4.1 第一遍以21天为周期没有周期的刷题坚持不下去三个月刷完六百题的规划对大多数人来说是不现实的因为缺少短期里程碑。我见过相对靠谱的节奏是把第一遍压缩到21天每天六到八道题周末只做题解回顾不做新题。21天正好对应一个习惯养成周期也对应大多数公司笔试通知到正式笔试之间的间隔。第一遍的21天里目标不是“每道题都能独立写对”而是“每种算法范式都见过能说出它的典型标志”。比如看到“求最长回文子串”能想到中心扩展或DP看到“求区间最大值”能想到单调队列这种“知道该用什么方法”的能力比“能把代码完全写对”更优先。一个可行的21天分配表是这样时间段内容每日题量备注第1-3天数组、字符串基础6-8题双指针、前缀和、滑动窗口第4-7天链表、栈、队列6-8题双端队列在滑动窗口中的用法第8-11天树、递归、回溯5-6题二叉树遍历手写递归与非递归第12-14天排序、二分5-6题归并排序、快排必手写第15-18天动态规划、贪心4-5题背包问题、区间DP重点过第19-21天综合回顾3-4题只重写之前做错的题这个节奏的关键参数是“每天新题数不超过旧题回顾数”。很多人刷题失败不是题难而是旧题忘得比新题学得快导致挫败感。每天开头的三十分钟先重写前一天的代码这一条能救回一半的遗忘问题。4.2 难度梯度按题型而不是按平台热度分牛客的题目列表是按热度排序的热度高的题往往集中在某些固定题型上比如链表反转、快排、斐波那契。如果你只看热度刷很容易陷入“简单题刷了几百道难题一道没碰”的状态。难点在于如何给自己的每个题型定难度级别而不是跟着平台走。更靠谱的做法是给每个题型建一个三级梯度入门题、核心题、拔高题。以字符串为例入门题是判断回文串、找最长公共前缀核心题是KMP、滑动窗口找最小覆盖子串拔高题是编辑距离、正则匹配这类DP与字符串的结合题。刷的时候只允许按照“入门→核心”的顺序走核心题没有全过之前不要碰拔高题。这个梯度不需要自己从零划分剑指Offer的题目天然天然就是入门到核心之间的过渡牛客BAT真题就是核心与拔高的混合体。所以你只要把自己要刷的题库按上述三类打标签就能得到一个梯度清晰的题单。打标签本身也是复盘的一种标签会提醒你哪些题型一直停留在“拔高题没碰”的状态。4.3 复盘粒度细化到“卡点”别写“这道题难”刷题笔记最大的误区是写“这道题用了DP有点难”。这句话三个月后没有任何信息量。有效的复盘要记录的不是难度而是卡点——你在哪一行代码上停住了为什么停在那一行。举个例子写“剑指Offer第46题把数字翻译成字符串”的复盘时不要写“DP好难”要写“卡在状态转移方程上没想清楚 dp[i] 依赖 dp[i-1] 和 dp[i-2] 的两种情况分别由什么触发。原因是对‘当前数字能否和前一个数字组成两位数’这个条件翻译不到位。”这样的记录两个月后复习时你看到它就会立刻回想起当时的思维阻塞点而不需要重新推导一遍。关于复盘频率我一般会定成“每次复习结束时写下三道题的最短卡点描述”并放在代码文件头部的注释里。就像这样# 题意简述: 把数字翻译成字符串有多少种翻译方式 # 卡点: 忘记判断 10 当前两位 25 的边界 # 解法: dp[i] dp[i-1] (可组合时?) dp[i-2] def solve(data): ...这个注释在两个月后重写代码时特别有用——它是逼着自己先回想卡点的起点而不是直接看完整题解。重写代码时由于注释只记卡点和思路不写完整代码所以不会变成“抄答案但看不下去”的情况。5. 刷题避坑指南五个最常见的翻车现场与对应解法5.1 现象题解看得懂自己写就卡壳这个问题不是智力的锅而是“阅读代码”和“生产代码”用的不是同一套脑回路。看题解时你的注意力是顺着别人写好的逻辑走的大脑会默认“这里自然递进过去了”但自己写的时候你要自己决定每一步的边界条件、空值处理、循环终止条件。所以我始终建议在看完题解后立刻关上答案自己从头默写一遍即使磕磕绊绊也要写完再比对。解决步骤先看题解合上立刻手写写不出来就再看一遍但每次重看必须把没写出的那一行标注出来。5.2 现象刷了三百题笔试还是没做出来原因往往不是刷题量不够而是题目分布不均。三百题里如果有两百道是数组和链表树和DP只有三十道不到那笔试碰上高频的DP题基本靠蒙这是结构性问题不是态度问题。解法是查一下自己在每类题型上的完成数低于总量的15%的题型要补上来。牛客、剑指Offer、九章这三套材料覆盖的题型侧重点不同跨材料对照就能发现自己偏科。别只刷自己擅长的题型这是一种舒适的逃避。5.3 现象两个月后复习发现全忘了忘了是正常的忘了才是符合客观规律的。但“全忘了”只有一种可能第一遍刷的时候没有做任何结构化整理代码文件是一堆题号的散装堆叠。解决方法是回到目录结构那一步把代码按题型重排并给每道题加上卡点注释。复习时不是按做题时的顺序看而是按题型把同一类的题一起重写一次。这样做最大的好处是同类题重写时框架是相似的你只要改核心逻辑大脑的负担大幅降低。5.4 现象本地跑得通OJ提交超时或超内存这背后是对空间复杂度理解不足。本地数据规模小时间复杂度差两倍根本感知不到但OJ的用例是按题目给出的数据范围设计的暴力枚举算法在本地不超时线上就会直接跑满。解决方法是养成分析数据范围的习惯凡是看到n 10^5的参数必须从一开始就确认算法复杂度不能是O(n^2)。刷题时先想复杂度再动键盘而不是先写完再说。5.5 现象环境配置把刷题兴趣耗光了这是个隐藏很深的问题。不同版本的Python在切片、内存占用、sys.setrecursionlimit默认值上表现差异很大。比如递归解法在n1000时直接超递归深度限制这在本地跑不出来你会误以为是自己算法写错了结果是Python解释器在默认限制下不跑深层递归。解决办法是提前在项目根目录放一个requirements.txt并且在每个题的代码头部注明“需要设置sys.setrecursionlimit吗”。用虚拟环境固定Python版本是刷题项目的第一笔基建投资。6. 用两小时盲写验证两个月后的复习成果一套可复现的收尾动作复习完一轮、代码全部重写一遍之后最后一个动作是“盲写两小时”。流程很简单从每类题型里随机抽一道题共抽六道左右不看任何题解和注释限时两小时独立完成然后拿第一遍的代码和这次的新代码做对比看差异在哪里。对比的重点不是“新代码比旧代码短了多少”这种虚荣指标而是关注三件事第一边界条件处理比上次稳还是不如上次第二有没有发现上次写了一个隐藏的bug但当时因为是照着题解抄的所以没暴露第三新代码是否更简洁比如交换变量不再用临时变量循环边界从调整到了配合1的写法。这三项观察才是复习最大的收获。如果盲写两小时后六道题有五道以上能独立完成那数据结构与算法刷题全攻略这个项目的核心目标就已经达到了。如果你发现某类题卡壳明显不用慌这恰恰说明两个月前的第一遍就没有在这个题型上形成肌肉记忆补刷的时候把同类题再集中来一轮即可。这套盲写验证法我在自己带过的几次小小学习小组里试过“第一遍看懂的题到第二遍盲写时面目全非”是常态但坚持用这种复盘节奏的人通常两三周后就能很快能认出题目背后的算法原型。盲写没过的题重新排序往往比赶着刷新题更重要。祝刷题路上的你早日不再闻算法变色希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Android Studio 2021.2.1.10 Windows离线包部署与避坑指南

Android Studio 2021.2.1.10 Windows离线包部署与避坑指南

简介:Android Studio Chipmunk(2021.2.1)Beta 3 的 Windows 版安装包,面向需要在 Windows 平台搭建 Android 开发环境的移动开发者、学生与教学人员。作为 2021.2.1 分支的花栗鼠版本,它介于 Bumblebee 与 Dolphin 之间…

📅 2026/9/30 14:48:39
大模型训练与推理优化(一)

大模型训练与推理优化(一)

大模型训练与推理优化 1. GPU 时间计算基础1.1 GPU 计算中的基本概念 h:hidden size,隐藏维度L:Transformer Block 层数V:词表大小参数量、FLOPs、显存和训练时间之间存在直接联系 1.2 Transformer 模型参数计算 1.2.1 Self-Atten…

📅 2026/9/30 14:43:38
IGBT门极电阻怎么算?门极适配与保护电路设计|硬件篇·14

IGBT门极电阻怎么算?门极适配与保护电路设计|硬件篇·14

前言 450A的IGBT,门极电阻选多大合适?开通和关断电阻为什么要分开?退饱和检测怎么接才能不误触发? IGBT驱动核选好了(见硬件篇十三),门极适配电路才是真正决定开关性能的环节。本文以英飞凌 FF4…

📅 2026/9/30 14:43:38
MORE NEWS

更多资讯

📰

从零搭建AI工程体系:避开调包陷阱,构建稳定可迭代的AI系统

1. 从零搭建AI工程体系,为什么我劝你别急着调包很多人一提到AI工程,第一反应就是pip install transformers,然后找个预训练模型跑个demo,觉得这就是AI工程了。我刚开始也这么想,直到真正接手一个需要上线的项目&#x…

📰

SpringBoot+Vue大学生就业招聘系统:从数据库设计到权限控制全解析

1. 为什么大学生就业招聘系统是课程设计的“黄金题目” 每年到这个时间点,后台总有人问我课程设计选什么题目。我的回答一直很明确: 带角色权限的Web业务系统,首选大学生就业招聘系统 。原因很简单——它不像图书管理、学生选课那种“纯增删…

📰

录像机接显示器大画面黑屏,小画面正常排查指导

一、问题现象录像机接显示器大画面黑屏,小画面正常二、组网三、关键点四、排查步骤优先确认界面是否有报错报错1:资源不足一般是主码流分辨率超出录像机解码能力,按照以下方法调试步骤一:确认录像机解码能力,核实相机视…

📰

双屏显示器设置完全指南:从分辨率缩放到刷新率优化

最近帮人调了几台双屏工作站,发现很多人对系统里"显示设置"这个面板的理解还停留在"能改分辨率就行"的层面。实际上,当你真正添加第二块、第三块屏幕时,涉及的东西远比想象中多——分辨率、缩放比例、排列顺序、刷新率、…

📰

2026 代理网络平台推荐指南:五家服务商实测打分,钱该给谁?

大家好,我是桃花键神。 先问大家一个问题:2026 年了,买个代理网络(Proxy Network),怎么反而比以前更难选了? 因为买家变了。以前用代理的「用户」是爬虫工程师,比的是谁家 IP 池大…

📰

ClawPanel 技术架构解析:Vanilla JS + Rust Tauri 多引擎零框架设计为何胜出

ClawPanel 技术架构解析:Vanilla JS Rust Tauri 多引擎零框架设计为何胜出 【免费下载链接】clawpanel 🦞 OpenClaw & Hermes Agent 多引擎 AI 管理面板 — 内置 AI 助手(工具调用 图片识别 多模态),一键安装 |…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬