news 2026/10/6 13:41:28

考研数据结构算法题36页总结:408和893代码大题高分攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
考研数据结构算法题36页总结:408和893代码大题高分攻略

简介:一份面向计算机考研408与893自命题考生的数据结构算法题总结,36页PDF浓缩了数组、链表、栈、队列、二叉树等核心结构的常考题型,涵盖合并排序数组、约瑟夫环、栈实现队列、最小栈、循环队列、链表删除/反转/环入口、二叉树前中后序与层序遍历、排序与Top K问题、双指针、二分查找、贪心及动态规划等机试高频题。每个题目给出C语言实现与关键思路,适合对照练习和快速复盘。内容按数组合并排序、链表操作、二叉树遍历、排序算法、递归与非递归、图遍历等模块清晰编排,基本覆盖考研算法题的主要出题方向;代码风格简洁,便于直接理解运行逻辑。资源本身是单个PDF文件,共36页,约1.67MB,方便在手机、平板或电脑上阅读,也适合打印成纸质版做冲刺笔记。目前已有1681人学习下载,对于正在刷leetcode或准备自命题机试的同学,是一份高性价比的浓缩复习资料,能节省大量整理时间并快速定位薄弱环节。

1. 考研数据结构算法题总结36页,拿到手先看什么?

九月中旬我开始刷408真题,发现最耽误时间的不是选择题,而是每年最后那道15分的代码大题。当时手上资料不少,但没一份能直接告诉我“考场上怎样把代码写到不丢分”。《考研数据结构算法题总结36页(893+408)》是我复习后期翻得最勤的一份资料,它把两套考纲交叉后的高频算法点按题型压成36页,每一页都是“题干+思路+代码+复杂度”四件套。适合两类人:跨考、手写代码心里没底的人;复习时间紧、想快速找回手感的人。先说结论:它替代不了真题,但能帮你把代码题从“玄学”变成“公式”。

2. 先拆408和893的命题差异:这份总结按什么逻辑编排

2.1 408统考算法题的命题边界:两道大题、复杂度红线

408统考的数据结构大约占45分,代码题一般出现在综合应用题里,通常是最后一道15分的大题,偶尔前面还会有一个小的算法设计填空。题目风格是“给你一个场景,写核心代码并分析复杂度”,比如给定一个链表,要求O(n)时间删除倒数第K个结点。这种题LeetCode上有原型,但考场上没有测试数据,阅卷只看三段:逻辑是否完整、边界是否覆盖、复杂度是否达标。

复杂度是408明确会关注的一条线。评分标准里经常写着“时间复杂度O(n)得满分,O(n^2)给一半”。所以这份总结里每道题都单独标注了时间复杂度和空间复杂度,我当时的做法是每页先看复杂度要求,再看题目描述,最后才对思路。如果你和我一样是从代码量开始复习的,建议把这个顺序反过来,先逼自己养成看复杂度的习惯。

提示:408代码题的复杂度红线一般是O(n)或O(n log n)。如果题目没给数据规模,默认不能出现双重循环。

从覆盖内容看,36页对应的是考研数据结构的七个章节:线性表、栈与队列、串、树与二叉树、图、查找、排序。看起来和各教材目录一样,但它的编排不是按章节,而是按“考察方式”走。比如链表和数组被放在同一组,因为它们经常以相同题型出现;图的遍历和树的遍历也归在一起,因为套路一样。这是这份资料和教材目录最大的区别:教材按知识结构组织,它按答题套路组织。

2.2 893自命题的差异:偏基础还是偏综合

如果说408是“全国统一难度”,893就是“每个学校各自出题”。同样是考数据结构算法题,A学校可能出三道手写代码,B学校可能出五个算法填空,C学校甚至直接从教材习题里挑原题。刷多了893真题会发现,自命题普遍比408更贴近教材,也更容易出现“直接背模板就能写”的题。

这里有两个常见误区:一是认为自命题比408简单,随便刷刷就行;二是把LeetCode的中等难题刷遍了,回来自命题简单题却写不顺。真实的893命题有两个明显特点:第一,题目描述通常很长,会给你完整的结构体定义和函数签名,实际上是把代码框架都搭好了,你要填的是核心逻辑;第二,它允许的复杂度往往比408宽松,很多题O(n^2)就能拿满分,前提是你必须老老实实把代码写完整。

对比维度408统考893自命题
题目来源改编经典算法,偏应用场景教材习题原题居多,偏基础
代码量一道大题15分,代码量中等3~5道小题,单题代码量小
复杂度要求严格,O(n)/O(n log n)相对宽松,O(n^2)常可接受
判分重点思路+复杂度+边界代码完整度+能否运行
复习策略练变体题背教材代码模板

这张对比表是我复习时自己整理的,后来对照这份总结的目录发现,它对两种考试的处理方式不一样:通用题型会标注“408/893均适用”,偏教材原型的题会单独标“893常考”,偏场景改编的题标“408常考”。这个细节帮我省了很多时间,因为自命题复习到后期,我基本只挑“893常考”的页面过,408的大题再单独练变体。

2.3 36页总结怎么用:一轮复习和冲刺阶段的不同打开方式

同样是36页,一轮复习和考前两周的用法完全不同。我第一遍复习时,是把这个总结当题库用的:先看题目,不看答案,在草稿纸上写核心代码,再和答案对照。这个过程非常费时间,一页可能花掉四十分钟,但收获也是最大的,因为代码题只有自己写过一遍才算真的会了。

到了十月下旬,时间紧起来,我换了一种方式:每天早中晚各翻十页,只读“题干+复杂度”两行,然后在脑子里过一遍解题步骤,最后只看代码里的关键三行。这个阶段的目的不是写代码,而是保持对题型的敏感度。真正的冲刺阶段,我反而把总结放回抽屉,改成用真题模拟考场,每套真题做完之后再翻总结,看自己哪一类题失分,再回到对应页面去补。

阶段时间建议打开方式目标
一轮复习9~10月先做题再看答案建立手写能力
强化阶段10~11月只看题干想思路训练题型识别
冲刺阶段考前两周真题为主+总结补漏保持手感和节奏

我特别想提醒的一点是:不要把这份总结当成“背多分”资料从头背到尾。它36页,按题型压缩过,但仍然需要你动笔。我在第二轮曾经偷懒只看答案,结果模拟考时连单链表反转都写得磕磕绊绊。从那以后我给自己定了个规矩:看一页总结,至少要在白纸上写十行代码才能翻下一页,不管代码是不是和答案一致。

3. 字符串与数组高频题复现:从暴力枚举到KMP

3.1 暴力枚举不是笨办法:先写对然后再优化

考场上最容易出现的情况是:拿到题就想最优解,想了十分钟没思路,最后连暴力解也没时间写。暴力枚举在算法题里听起来不高级,但它是手写代码的基本功。一个不超时的暴力解,配合清晰的注释,在408里至少能拿六成分数,在893自命题里甚至能拿满分,因为很多自命题根本没限制复杂度。

以LeetCode上最经典的“两数之和”为例,题目给一个数组和一个目标值,要求返回两个下标。很多人的第一反应是哈希表,但考场上如果一时间想不起哈希表怎么写,暴力枚举完全够用:

def two_sum(nums, target): # 暴力枚举:固定一个数,往后找补数 n = len(nums) for i in range(n): for j in range(i + 1, n): if nums[i] + nums[j] == target: return [i, j] return []

这段代码的逻辑很简单:外层循环固定i,内层循环从i+1开始扫,避免同一对元素被重复统计。时间复杂度O(n^2),空间复杂度O(1)。两个参数里,nums是输入数组,target是目标值,返回的是下标列表。注意内层循环起点是i+1而不是0,这是最容易写错的地方,写成0会多算很多无效pair,极端情况下会出现自身加自身等于target的错误。

如果题目要求O(n),再往哈希表版本升级:

def two_sum_hash(nums, target): seen = {} # 值 -> 下标的映射 for i, x in enumerate(nums): need = target - x if need in seen: return [seen[need], i] seen[x] = i return []

这个思路的关键是“边查边存”:当前元素查需要的补数是否已经出现过,再把当前元素存进哈希表。这样每个元素只扫一遍,时空复杂度都是O(n)。考研答题时建议把哈希表版本的注释也写上,尤其是“need = target - x”这一步,阅卷人一眼就能看出你思路清楚。

我在复习中发现的规律是:数组类算法题,暴力解往往是理解题意的第一层,最优解是第二层。资料里数组部分的题目基本都给了两层答案,我先抄一遍暴力解,再抄一遍优化解,对比两个版本的差异,这样比直接背最优解要牢得多。

3.2 KMP的核心:next数组和退化场景

KMP是字符串匹配里的高频考点,408和893都可能直接考“写出next数组”或者“用KMP算法求匹配位置”。很多复习到KMP就放弃的人,其实是死在了next数组的求法上,因为不同教材对next的定义不一样,有的从0开始,有的从1开始,有的用-1,手写的时候一混就全错了。

我用的版本是考研最常用的next数组定义:next[0] = -1,-1表示主串指针也要后移;next[1] = 0,因为第一个字符失配时没有前缀可以回退。求next的代码写下来是这样:

// p: 模式串, next: 长度为模式串长度的数组 void get_next(char *p, int *next) { int i = 0, j = -1; next[0] = -1; while (p[i] != '\0') { if (j == -1 || p[i] == p[j]) { i++; j++; next[i] = j; // 当前前缀长度就是i失配时要回退的位置 } else { j = next[j]; // 不匹配,回退到更短的前缀 } } }

这里最核心的是else分支里的“j = next[j]”。很多初学的人在这个位置写成了“j = 0”,表面上看也能跑通部分用例,但遇到真回退时会漏掉已有匹配。i是当前正在比较的主串位置,j是模式串中已匹配的长度。每轮循环要么i和j同时前进,要么j回退到next数组指向前的位置,这样保证i不回头,整个匹配过程线性。

理解完next数组,KMP匹配本身反而简单:主串和模式串一起走,失配时模式串跳到next[j],主串不回溯。408一般不要求写完整的KMP匹配函数,更多是给你一个模式串让你手算next数组,或者给你next数组让你分析匹配过程。我在资料里看到KMP这部分时特别注意了它给的“退化场景”:如果模式串全是同一个字符,比如“aaaa”,next数组是递增的,但匹配时的比较次数依然不会退回O(mn),这就是KMP的价值所在。

3.3 双端队列与单调队列:小众但能救场

双端队列在数据结构教材里是一个线性表考点,但代码题里它经常以“单调队列”的形式出现。最经典的场景是滑动窗口最大值:给一个数组和一个窗口大小k,求窗口从左滑到右每个位置的最大值。暴力做法是每个窗口扫一遍,时间复杂度O(nk);用双端队列可以压到O(n)。

from collections import deque def max_sliding_window(nums, k): q = deque() # 存下标,下标对应的值从队头到队尾递减 res = [] for i, x in enumerate(nums): if q and q[0] <= i - k: q.popleft() # 队头下标已经滑出窗口,直接移除 while q and nums[q[-1]] <= x: q.pop() # 队尾元素不大于x,它再也不会成为最大值 q.append(i) # 当前下标入队 if i >= k - 1: res.append(nums[q[0]]) # 队头就是当前窗口最大值 return res

这段代码的注释已经把每个分支都说明了。队头存的是窗口内最大值的下标,队尾存的是有可能成为最大值的候选下标。第一次写这个题的人,通常会在“队尾弹出”这一步犹豫,拿不定该弹出小于还是小于等于当前值的元素。我一般建议弹出“不大于当前值”的所有下标,也就是用<=,这样重复元素也能正确处理。

在自命题考试里,如果考纲里出现了双端队列,滑动窗口最大值几乎就是必背模板。即使是408没考过这个场景,它也是一种通用思路:用双端队列维护一个单调序列,可以解决很多“找区间最值”的问题,比如求每个长度为k的子数组最小值、求滑动窗口中的中位数等等。把这些场景在总结里记在一起,比孤立记“双端队列”四个字有用得多。

4. 树与图算法题怎么练:排序、遍历与递归返回值的取舍

4.1 冒泡排序与堆排序:408爱考过程,893爱考代码

排序是考研数据结构算法题里性价比最高的一块,因为它既容易出大题,也容易出选择题。408和893对排序的考法有明显差异:408喜欢考“过程”,比如给你一个初始序列,让你写出冒泡排序第一趟和第二趟之后的结果,或者问比较次数;893则更喜欢直接让你写出完整排序函数,甚至给你结构体数组,按成绩字段排序。

以冒泡排序为例,标准代码几乎每个考场都会用到:

def bubble_sort(a): n = len(a) for i in range(n - 1): swapped = False for j in range(n - 1 - i): if a[j] > a[j + 1]: a[j], a[j + 1] = a[j + 1], a[j] swapped = True if not swapped: break return a

这里的swapped标志位是区分“标准冒泡”和“优化冒泡”的关键,它的作用是在某一趟没有任何交换发生时提前终止。对408的选择题来说,这个标志位会影响“最少趟数”的结论;对893的手写题来说,写上它能体现你对内层循环边界的理解。注意内层循环的范围是n-1-i,因为每一趟结束后,最大的i+1个元素已经沉到底部,不需要再参与比较。

堆排序在考研代码题里出现的频率更高,因为它的过程更复杂,适合出成“手写建堆”或“手写调整”。核心是堆调整函数:

def heapify(a, n, i): largest = i left = 2 * i + 1 right = 2 * i + 2 if left < n and a[left] > a[largest]: largest = left if right < n and a[right] > a[largest]: largest = right if largest != i: a[i], a[largest] = a[largest], a[i] heapify(a, n, largest) def heap_sort(a): n = len(a) for i in range(n // 2 - 1, -1, -1): heapify(a, n, i) # 从最后一个非叶子节点开始建堆 for i in range(n - 1, 0, -1): a[0], a[i] = a[i], a[0] # 堆顶与末尾交换 heapify(a, i, 0) # 新的堆顶调整,堆大小减1 return a

我写这段代码时最容易错的是“建堆循环的范围”。n//2-1是最后一个非叶子结点的下标,从它开始往前逐个调整,才能保证整个数组成为大根堆;如果从0开始往下调,会出现局部有序但全局没排好的情况。交换a[0]和a[i]之后,堆的有效长度变成i,所以第二次heapify传的是i而不是n。堆排序时间复杂度稳定在O(n log n),空间复杂度O(1),但要注意它是不稳定排序,408选择题经常拿这个当考点。

4.2 图的遍历:邻接表与邻接矩阵的取舍

图的数据结构题在408里一般以应用题出现,在893里则以手写遍历居多。最常见的两个考点是深度优先搜索和广度优先搜索。实现方式取决于存储结构:邻接矩阵写起来最简单,查两点是否相邻是O(1),但遍历所有邻接点要扫一整行;邻接表写起来要处理指针或链表,但遍历时只访问实际存在的边,复杂度是O(V+E)。

存储结构判断两顶点是否相邻遍历顶点v的邻接点适用场景
邻接矩阵O(1)O(n)稠密图、选择题判断
邻接表O(degree(v))O(degree(v))稀疏图、手写遍历代码

对代码题来说,我更推荐用邻接表,理由其实就一句话:代码量不大,复杂度又好写清楚。一个简单的DFS如下:

def dfs(adj, visited, u): # adj: 邻接表,visited: 布尔数组,u: 当前顶点编号 visited[u] = True print(u, end=" ") for v in adj[u]: if not visited[v]: dfs(adj, visited, v)

这段代码的逻辑是教科书标准版,但有一个细节常被忽略:visited[u] = True必须放在递归调用之前,不能放在循环之后。如果你先遍历邻接点再标记当前点,同一层里会出现大量重复打印,甚至因为相互引用导致递归无法终止。递归结束后不需要还原visited,因为图遍历要求每个顶点只访问一次;只有求所有路径时才需要回溯还原,那是另一类题。

BFS的代码和DFS长得像,区别只是把系统栈换成显式队列:

from collections import deque def bfs(adj, visited, start): q = deque([start]) visited[start] = True while q: u = q.popleft() print(u, end=" ") for v in adj[u]: if not visited[v]: visited[v] = True q.append(v)

这里最容易踩坑的是入队时就要立刻标记visited。如果你等出队时再标记,同一个节点会被多个邻居重复入队,在小规模数据上可能看不出问题,但在有环的图里会直接死循环。我把“标记”和“入队”视为一个原子操作,写BFS就不会乱。

4.3 树的递归:返回值设计决定成败

树的算法题是自命题的最爱,因为它代码短、逻辑清晰、适合手写。最常见的是求树的高度、判断平衡二叉树、求直径、最近公共祖先。这类题统一用递归解决,关键是设计好递归函数的“返回值”。我见过很多翻车代码,不是递归写不出来,而是返回值定义模糊,导致上层调用没法判断结果。

先看最简单的求二叉树高度:

def tree_height(root): if not root: return 0 left_h = tree_height(root.left) right_h = tree_height(root.right) return max(left_h, right_h) + 1

这里的返回值定义很明确:返回以root为根的子树高度。空节点高度是0,叶子节点高度是1。递归过程是自底向上的:先问左子树多高,再问右子树多高,取较大值加1。这种设计不需要额外参数,也天然处理了只有左子树或只有右子树的非平衡情况。

如果题目升级成“判断是否是平衡二叉树”,就不能只返回高度了。我常用的做法是让递归函数返回两个信息——子树高度和是否平衡,用一个特殊值表示“不平衡”:

def is_balanced(root): def check(node): if not node: return 0 lh = check(node.left) if lh == -1: return -1 rh = check(node.right) if rh == -1: return -1 if abs(lh - rh) > 1: return -1 # -1 表示不满足平衡条件 return max(lh, rh) + 1 return check(root) != -1

这个版本的返回值设计是:正常情况返回子树高度,一旦发现左右子树高度差超过1,立即返回-1,让上层递归剪枝。注意两个if的判断顺序:先检查左子树是否不平衡,再看右子树,这样能提前结束递归,避免做无意义的深度累加。如果只按“算高度再单独判断”的写法,每个节点会被重复访问多次,时间复杂度会从O(n)退化到O(n^2)。

树的递归题我总结出一个通用流程:第一步定义返回值的含义,第二步确定空节点返回值,第三步想清楚当前节点如何组合子节点的返回值,第四步写边界。36页总结里树的题目其实都是这四步,区别只在第3步的组合方式不同。

5. 算法题刷题避坑:五个高频翻车现场与修复方案

5.1 样例过了,交上去全错

现象:做模拟题或自命题机试时,题目给出的示例输入跑一遍完全正确,自己额外造几组数据就崩了。比如链表题,示例是1->2->3->4,删除倒数第2个节点,输出1->2->4,没问题;换成5个节点的链表,或者链表只有1个节点,程序直接报错或返回空。

原因:只按示例数据写代码,没有覆盖边界条件。考研手写代码虽然没有测试用例,阅卷时会按步骤给分,边界处理是评分表里明确的一档,缺失会整体降档。

解决:写任何题之前,先问自己三件事:输入为空怎么处理?只有一个元素怎么处理?重复元素怎么处理?把这三个分支在代码里显式写出来,即使不完整,阅卷人也能看到你在考虑边界。我后来给自己定的习惯是,每写一个函数,至少测三组数据:正常数据、最小数据、重复数据。

这里尤其要提链表类题目,单链表删除的代码很容易在只有一个节点时越界。我考前专门把“空链表、单节点、头节点被删”三种情况抄在总结的空白页上,每天看一遍,后来再遇到删除类题目基本能条件反射地补上判断。

5.2 KMP的next数组背了又忘,手写时死循环

现象:考场上写get_next,while循环里忘记让i前进,代码一跑就死循环,或者next数组结果跟标准答案对不上。

原因:next数组的标准代码依赖“j回退到next[j]”这个动作,死循环通常是因为把else分支的“j = next[j]”写成“j = 0”,在特定模式串下j会一直停在0,i永远不动。

解决:先不看代码,自己手推一次next数组再对照。推荐记两个锚点:next[0]=-1,next[1]=0。写代码时盯着else分支,不匹配就必须让j回退,回退不出去就把j=next[j]打印出来看,确认j在递减。这个坑我在模拟考翻过两次,后来每次写KMP都会先画一遍模式串的前后缀表,画完再写代码,基本不会再错。

如果你用的是从1开始的教材定义,那就整份资料都用那一套定义,千万别一套题里混用两种next。阅卷人按答案步骤给分,定义混用会导致后面的匹配过程完全对不上,丢分会非常可惜。

5.3 树的递归栈溢出或死循环

现象:代码看起来没问题,但遇到深度较大的树时程序崩溃,或者递归结束后输出重复结果。

原因:递归终止条件写错是最大隐患。常见错误是“只判空节点返回0,但不判当前节点是否为空”,导致空节点的left被访问;另一个错误是递归函数里重复调用自身但方向不对,比如求树高度时把左子树的递归写在右子树的返回值里,导致无限递归。

解决:树递归的终止条件必须在函数第一行,先判空再访问属性。如果发现死循环,优先检查是不是在递归入口就访问了node.left而没有判node本身为空。我自己的检查方法是把递归函数的第一行固定写成“if not node: return 0”,形成肌肉记忆,写树题就不再翻车。

更深一层的问题是“递归返回值类型”没想清楚。树的高度返回int,判断存在性返回bool,这两个东西不能用同一个模板硬套。我在资料上看到树的章节特意把两类题目分开排版,就是为了避免把返回值的语义搞混。

5.4 时间复杂度被扣分:只算最好情况

现象:自认为算法复杂度达标,结果被阅卷或面试官问住,因为写的代码在“最坏情况”下反而退化到O(n^2)。比如哈希表扩容分析,或者快速排序在基本有序时退化成O(n^2)。

原因:默认输入是随机的,没考虑极端输入;快排的哨兵取第一个元素,遇到降序数组每次只能排一个元素。

解决:分析复杂度时一律按最坏情况写出来,快排写“平均O(n log n),最坏O(n^2)”。408评分看重复杂度的分析过程,哪怕代码里用的堆排序,只要把复杂度边界写清楚,至少能拿步骤分。我在总结里看到快排那页旁边手写了一行“哨兵取中间位置”,就是用来提醒自己最坏情况的来源。

更实用的做法是给代码里的关键循环打标注。比如“for i in range(n): for j in range(i+1,n):” 直接在注释后写“O(n^2)”,这样一眼就能看到哪一段是复杂度瓶颈。阅卷人不需要你去解释,标注本身就是得分点。

5.5 盲目刷LeetCode,自命题反而写不顺

现象:LeetCode刷了几百题,模拟893自命题时,遇到课本原题却无从下手,或者写出来的答案不符合题目要求的函数签名。

原因:LeetCode强调的是最优解、异常输入、极端用例,所有代码都要在编译器里跑;考研手写代码更强调代码可读性、结构体定义匹配、注释清晰。两者评分标准不一样。

解决:分清两者的时间分配。我在冲刺期把LeetCode当成“锻炼思路”的工具,刷题时只看题解思路,不在编辑器里调一晚上;手写代码用真题和总结里的题目练,要求自己能在十五分钟内写完一题,不能改不能重跑。真正上考场时,代码是直接写在答题纸上的,没有编译器帮你检查,平时训练就应该闭卷写。

这里还有一个小技巧:893自命题如果给了结构体定义,答题时先原样抄一遍结构体,再写函数体。很多学校是按“结构体定义是否正确”给分的,抄错一个字段名就可能丢掉一整档分。我见过好几个同学在自命题考场上因为没写结构体,代码逻辑全对但只拿了一半分,非常冤。

6. 最后两周的收尾技巧:复杂度口算与答题模板化

6.1 一个数,快速判断你的算法能不能过

考研没有在线评测,但复杂度分析要写在答题纸上。我有个笨但实用的方法:先看题目是否给数据规模,给了就估算一个数量级,然后对照下面这张表,判断你的方案是否在安全线内。

数据规模n可用复杂度典型算法
n <= 10O(n!)全排列暴力
n <= 20O(2^n)状态压缩、剪枝搜索
n <= 10^3O(n^2)冒泡、暴力枚举
n <= 10^5O(n log n)快排、堆排、KMP
n <= 10^7O(n)双指针、哈希表

更关键的是,408代码题一般不会给你特别大的n,它的目的是让你写出“复杂度正确”的算法,而不是真去跑数据。所以答题纸上写的复杂度分析,必须和你的代码实现完全对应。哪怕你实际用了O(n^2)的暴力解,你写“时间复杂度O(n^2)”,也比写了O(n)却实现得不对要好。

6.2 三个背下来就能救场的模板

最后两周我不再追求新题,只过三个高频模板:双指针判断回文、单链表反转、二叉树递归遍历。这三个模板覆盖了数组、链表、树三类最常见的代码题。

# 双指针判断回文,背下来的模板 left, right = 0, len(s) - 1 while left < right: if s[left] != s[right]: return False left += 1 right -= 1 return True
# 单链表反转模板 def reverse_list(head): prev = None cur = head while cur: nxt = cur.next cur.next = prev prev = cur cur = nxt return prev

每个模板都对应一类题型。双指针是“一对多”题型的基础,还能推广到有序数组的两数之和、删除重复元素;单链表反转是所有链表题的基础,很多链表大题的核心步骤就是在局部做反转;二叉树递归模板其实就是前面写的判空、递归左右孩子、组合返回值那三步。把这三个模板写在总结第1页,每天默写一遍,比刷十道LeetCode更稳。

6.3 考场上最后五分钟查什么

我模拟考时养成了一个习惯:代码写完后不急着做下一题,回头检查三个位置——递归的终止条件有没有写在第一行,循环的边界是小于还是小于等于,有没有返回空值。这三个位置占了代码题80%的低级错误。从那以后我每次模拟考都强制走一遍这三查,自命题考试的最后一道代码题,基本能在十分钟内干干净净写完。这份36页的总结不一定完美,但它帮我稳住了最不踏实的一块,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 13:40:59

Superpowers:在VS Code里一站式搞定Supabase认证、RLS与Edge Functions

做Supabase项目的朋友应该都有这种感觉&#xff1a;代码写在了VS Code里&#xff0c;可真正的开发工作却有大半是在浏览器后台完成的。Authentication要开好几个登录Provider&#xff0c;回调地址一个个填&#xff1b;RLS策略写错了&#xff0c;得切到SQL Editor去看报错日志&a…

作者头像 李华
网站建设 2026/10/6 13:40:17

OpenClaw部署实战:环境检查、WSL2配置与Skill接入

简介&#xff1a;这份《养龙虾OpenClaw》课件是一套面向AI开发者的OpenClaw实战教学材料&#xff0c;围绕智能体原理、系统架构、OpenClaw实现、部署实践与应用扩展五章展开&#xff0c;适合技术分享、课程讲授和自学进阶。内容从智能体的定义、感知—决策—行动模型与记忆模块…

作者头像 李华
网站建设 2026/10/6 13:39:46

MyBatis-Plus核心原理与企业级最佳实践:从CRUD到生产优化

大概两年前&#xff0c;我接手了一个遗留系统&#xff0c;DAO 层全是手写的 JDBC 模板和 XML SQL&#xff0c;一个订单查询能拼接出十几行动态条件&#xff0c;Service 层一大半代码在做数据搬运。后来换到新团队&#xff0c;发现新项目里几乎没人再手写单表 CRUD 了&#xff0…

作者头像 李华
网站建设 2026/10/6 13:39:08

C语言数据结构:栈实现数制转换的原理与代码实例

简介&#xff1a;一份介绍C语言数据结构中数制转换的PDF资源&#xff0c;面向正在学习数据结构和算法的初学者&#xff0c;重点演示如何借助顺序栈完成从十进制到八进制&#xff08;或其他进制&#xff09;的转换。文档从顺序栈的结构定义入手&#xff0c;逐段讲解栈的初始化、…

作者头像 李华
网站建设 2026/10/6 13:38:11

Superpowers:面向开发者的本地化AI编程增强系统

1. 项目概述&#xff1a;Superpowers 不是超能力&#xff0c;而是开发者工作流的“神经增强系统”你最近在 GitHub、Hacker News 或国内技术社区刷到 “superpowers” 这个词&#xff0c;大概率不是漫威电影彩蛋&#xff0c;而是一群工程师在深夜调试完 CI 流水线后发的一句感叹…

作者头像 李华
网站建设 2026/10/6 13:38:06

ASP.NET Web Forms邮件系统毕设实战指南

简介&#xff1a;本资源是一套面向计算机专业本科生的毕业设计实战项目&#xff0c;聚焦C/S架构下轻量级电子邮件客户端的开发实践&#xff0c;帮助初学者掌握SMTP/POP3协议应用、用户注册认证、邮件收发核心逻辑及联系人管理等关键功能。压缩包共147个文件&#xff0c;含36个C…

作者头像 李华