简介:面向军队文职考试计算机类科目考生的数据结构与算法知识点浓缩总结文档。内容覆盖基本概念、线性表、栈与队列、树与二叉树、图、查找与排序算法六大核心板块,从数据元素、数据项与逻辑结构/物理结构的定义,到顺序表随机访问与链表指针操作的实现差异,再到顺序表插入删除O(n)复杂度、栈的先进后出、队列的先进先出、循环队列空满判定、二叉树性质与三种遍历、图的邻接矩阵与邻接表、深度/广度优先搜索、最小生成树以及常用查找排序方法的归类对比,脉络清晰完整。包体为1个docx文件,大小661KB,便于随时查阅与集中复习。目前已有98人学习下载。文档按考点提炼了顺序存储与链式存储优缺点、算法五特性与设计要求、顺序表和单链表结构体定义等关键结论,可帮助考生快速建立知识框架、定位薄弱环节,适合作为军队文职考试计算机类备考冲刺阶段的重点复习资料。
1. 这份知识点总结,到底在解决什么问题
准备军队文职计算机类笔试的人,很多都卡在数据结构与算法这一科。它不是大学期末考那种背一背就能过的科目,考察方式更接近实际工程思维:给你一段代码问你时间复杂度,给一个场景让你选最合适的存储结构,或者直接让你手写一个排序或遍历的完整实现。而我看到这份《军队文职计算机类数据结构与算法知识点总结》文档时,第一反应是:这正是备考过程中最缺的东西——一份把考纲知识点、常考代码模板、易错细节全部压缩到一起的复习索引。它能解决的核心问题是:你不知道这门课到底考什么、每题背后在考哪个知识点、复习时该把精力押在哪里。适合三类人:跨专业零基础、大学学过但忘得差不多的在职考生、以及看完一遍教材却不知道从哪开始刷题的应届生。接下来我会按这份文档通常会覆盖的模块,把每个知识点怎么理解、怎么记、怎么练拆开讲清楚,并标注出考试里最容易翻车的地方。
2. 考情定位:数据结构与算法在笔试里的真实占比与考查方式
2.1 为什么这门课是计算机类岗位的公共科目分水岭
军队文职计算机类笔试中,数据结构与算法不只是专业科目里的一个章节,它更像一个地基:操作系统里的进程调度要讲队列,数据库里的索引要讲 B+ 树,计算机网络里的路由算法要讲图的最短路径。如果数据结构的地基不稳,后面所有专业课复习都会像在流沙上盖房子——每个章节都似懂非懂,做题全靠猜。从历年考题的分布来看,线性表、二叉树、排序和查找这四大块占了绝大多数分值,而图论和算法设计策略虽然考得少一些,但一出就是大题,区分度很高。所以复习策略上,我建议把 70% 的时间花在「必考且好拿分」的模块上,剩下 30% 去啃「难但能拉分」的内容。
2.2 题型分布与知识点权重参考
根据往年考试反馈,数据结构与算法的常见题型包括:选择题(约 10-15 题)、填空题(约 5-8 空)、简答题(约 2-3 题)、算法设计题(约 1-2 题)。考查权重可以参考下面的分配方式。
| 知识模块 | 题型分布 | 考查重点 | 复习优先级 |
|---|---|---|---|
| 线性表(顺序表/链表) | 选择、填空、简答 | 插入删除的时间复杂度、链表指针操作 | 高 |
| 栈与队列 | 选择、填空、简答 | 出入栈序列判断、循环队列判满/判空 | 高 |
| 树与二叉树 | 选择、填空、简答 | 二叉树性质、遍历序列互推、哈夫曼编码 | 高 |
| 图 | 选择、简答、算法 | 邻接矩阵/邻接表、DFS/BFS、最小生成树 | 中 |
| 查找 | 选择、填空、简答 | 二分查找、二叉排序树、哈希冲突处理 | 高 |
| 排序 | 选择、填空、算法 | 各排序算法复杂度、稳定性、手写快排 | 高 |
| 算法设计策略 | 简答、算法设计 | 分治、贪心、动态规划 | 低-中 |
关键判断:排序算法这一章是性价比最高的,因为它既能考概念(复杂度、稳定性),又能考手写代码(快排、堆排),而且答案标准、不易争议。但图论部分不要死磕太深的算法,能掌握 DFS/BFS 的代码框架和最小生成树两种算法的步骤就够了。
2.3 一份合格知识点总结应该有的目录结构
拿到任何一份知识点总结文档,先不要急着往下读,先用五分钟审视它的目录结构。合格的结构应该像一颗倒装的树:根是「数据结构与算法」,主干是「线性结构、树形结构、图形结构、查找、排序、算法设计」六大分支,每个分支下面是叶子节点——具体知识点。如果你打开这份文档发现它大段大段地复制教材原文、没有归纳没有对比表,那它的价值就要打折扣。好的总结文档,每个知识点都应该包含三样东西:一句话定义、考试常考的角度、一个易错点提醒。后面我会按这个标准来拆解每个模块的干货内容。
3. 线性表、栈与队列:最基础也最爱出细节题的模块
3.1 顺序表与链表:存储结构选择的判断标准
顺序表和链表的对比是选择题和简答题的常客。核心考点有三个:物理存储结构、插入删除的时间复杂度、按值查找的时间复杂度。顺序表是连续存储,随机访问 O(1),但插入删除需要移动元素,平均 O(n);链表是离散存储,随机访问 O(n),但插入删除只需要修改指针,已知位置时 O(1)。备考时最容易忽略的细节是:链表插入删除的 O(1) 是「已知前驱节点」的前提下,如果只给了值要去查找,那还是要 O(n)。这个「前提条件」几乎每年都有考生踩坑。
代码层面,链表操作是手写题的高频候选。我习惯让备考者背下来一个「创建链表并遍历输出」的完整模板:
class Node: def __init__(self, data): self.data = data self.next = None def create_linked_list(arr): """根据列表创建链表,返回头节点""" if not arr: return None head = Node(arr[0]) cur = head for val in arr[1:]: cur.next = Node(val) cur = cur.next return head def traverse(head): """遍历链表并打印所有节点值""" cur = head while cur is not None: print(cur.data, end=" ") cur = cur.next print() # 测试 head = create_linked_list([1, 3, 5, 7, 9]) traverse(head)这段代码里需要注意的参数和边界:create_linked_list 函数处理了空数组的特殊情况,返回 None;遍历逻辑用 while cur is not None 而不是 while cur.next is not None,这样才能访问到最后一个节点。考试手写时,最容易被扣分的地方就是忘记处理空链表,或者遍历条件写错导致最后一个节点的数据没输出。
3.2 栈与队列的六个必背性质
栈和队列的知识点密度很大,几乎每一页都能出一道题。必背内容我整理成口诀式的清单:栈是后进先出,队列是先进先出;栈的入栈出栈序列判断是选择常客;循环队列判满条件是 (rear + 1) % MaxSize == front;循环队列元素个数公式是 (rear - front + MaxSize) % MaxSize;栈用于函数调用、表达式求值,队列用于层次遍历、缓冲区。这里要特别强调循环队列判满和判空的区分——判空是 front == rear,判满是 (rear + 1) % MaxSize == front,这个「浪费一个存储单元」的约定很多初学者会懵。
关于出入栈序列判断,这里提供一个快速验证的模拟算法:用一个辅助栈,按照入栈序列依次压入,同时用一个指针指向出栈序列的当前位置,每压入一个元素就检查栈顶是否等于出栈序列当前指向的元素,相等则弹出并后移指针。最终如果辅助栈为空,说明该出栈序列合法。这个算法要能手写模拟,考试时要能在草稿纸上快速跟踪。
3.3 表达式求值与括号匹配:两道必会代码
括号匹配是栈应用的经典题目,几乎年年出现在算法设计或简答题里。核心思路是:遇到左括号入栈,遇到右括号时检查栈顶是否匹配,匹配则弹出,不匹配则直接判定错误。结束后栈必须为空才算匹配成功。备考者可以把下面这个 Python 实现作为模板记牢。
def is_valid_brackets(s: str) -> bool: """检查括号字符串是否匹配,如 ([]){} 返回 True 表示匹配,False 表示不匹配 """ stack = [] mapping = {')': '(', ']': '[', '}': '{'} for ch in s: if ch in '([{': stack.append(ch) elif ch in ')]}': if not stack or stack[-1] != mapping[ch]: return False stack.pop() return len(stack) == 0 # 测试用例 print(is_valid_brackets("([]){}")) # True print(is_valid_brackets("([)]")) # False print(is_valid_brackets("((()))")) # True这段代码的关键在于用字典建立右括号到左括号的映射,空间换时间,避免写多个 if 分支。参数说明:s 是仅包含括号字符的字符串;返回值是布尔类型。逻辑说明:检查到右括号时,如果栈为空说明右括号没有匹配的左括号,直接返回 False;如果栈顶不匹配同样返回 False。这个模板比多分支写法更简洁,阅卷时也更容易拿满分。
4. 树与二叉树:遍历互推、哈夫曼编码与代码模板
4.1 二叉树的三条核心性质与满二叉树/完全二叉树
二叉树性质是填空和选择的高频考点。第一条:第 i 层最多有 2^(i-1) 个节点;第二条:深度为 k 的二叉树最多有 2^k - 1 个节点;第三条:叶子节点数 = 度为 2 的节点数 + 1,也就是 n0 = n2 + 1。第三条性质应用极广,几乎遇到「求节点数」的选择题都要用到它。另外,完全二叉树中度为 1 的节点最多只有 1 个,这个结论在计算节点总数时非常有用——考试常给「完全二叉树有 1001 个节点,问叶子节点数」,解法就是先根据公式判断 n1 是 0 还是 1,再利用 n0 + n1 + n2 = 总数和 n0 = n2 + 1 联立求解。
满二叉树的概念要和完全二叉树区分清楚。满二叉树是每一层都满,节点总数是 2^k - 1;完全二叉树是除最后一层外每一层都满,且最后一层的节点都集中在左侧。这两个概念几乎每次考试都会在选择题里出现混淆选项。
4.2 遍历序列互推:从前序+中序还原二叉树的完整步骤
前序遍历是根左右,中序遍历是左根右,后序遍历是左右根。由中序序列加上前序或后序序列可以唯一确定一棵二叉树,但前序加后序不能唯一确定。这是考试重点,也是很多人的知识盲区。还原步骤是这样的:
第一步,从前序序列的第一个元素确定根节点;第二步,在中序序列中找到根节点位置,左边是左子树的中序序列,右边是右子树的中序序列;第三步,根据左子树节点个数回到前序序列中切分出左子树的前序序列和右子树的前序序列;第四步,递归重复前三步。这道题几乎每年都以简答题或选择题形式出现,必须做到能在 3 分钟内手工还原一棵树。
实战中容易出错的地方是第三步的切分。很多人知道要找根,但在切分前序序列时容易把左右子树的边界搞错。技巧是:先数左子树有几个节点(根据中序序列中根左边的元素个数),然后在前序序列中跳过根节点后,数同样数量的节点作为左子树的前序序列,剩下的就是右子树的前序序列。这个方法要反复练到形成肌肉记忆。
4.3 哈夫曼编码:构造过程、WPL 计算与编码规则
哈夫曼编码是简答题的常客。构造步骤:将权值从小到大排序,每次取最小的两个节点合并为一个新节点,新节点的权值为两者之和,重新参与排序,重复直到只剩一棵树。左分支标 0 右分支标 1,从根到叶子经过的分支串起来就是该叶子对应的哈夫曼编码。WPL(带权路径长度)等于所有叶子节点的权值乘以路径长度之和,也就是每次合并时两个权值相加的累计和。
这里有一个高频易错点:哈夫曼树不唯一,但 WPL 是唯一的。因为在构造过程中,如果遇到权值相同的节点,不同的合并顺序会生成不同形状的树,但总的带权路径长度不会变。考试如果问「哈夫曼树是否唯一」,答案是不唯一;如果问「WPL 是否唯一」,答案是最小且唯一。另一个细节是:哈夫曼树只有度为 0 和度为 2 的节点,没有度为 1 的节点,叶子节点数等于 n,则总结点数是 2n - 1。
4.4 二叉树遍历的递归代码模板与时空复杂度
手写二叉树遍历是算法设计题的基础款。三个遍历的递归实现差别只在访问节点的时机,代码结构几乎一样。以下以 Python 为例提供模板。
class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def preorder(root): """前序遍历:根 -> 左 -> 右""" if root is None: return [] return [root.val] + preorder(root.left) + preorder(root.right) def inorder(root): """中序遍历:左 -> 根 -> 右""" if root is None: return [] return inorder(root.left) + [root.val] + inorder(root.right) def postorder(root): """后序遍历:左 -> 右 -> 根""" if root is None: return [] return postorder(root.left) + postorder(root.right) + [root.val]这段代码里,三个函数的核心差异就是返回值拼接时 val 的位置。参数说明:root 是二叉树根节点,递归终止条件是 root 为 None,返回空列表。逻辑说明:递归调用左右子树时,结果用列表拼接的方式组织。时间复杂度都是 O(n),因为每个节点恰好访问一次;空间复杂度是 O(h),h 是树的高度,最坏情况(树退化为链表)是 O(n),这是递归代码的天然缺陷。如果考试要求写非递归版本,需要用显式栈模拟,这个进阶版本建议也备一份。
5. 查找与排序:复杂度对照表、稳定性辨析与手写代码
5.1 七大查找方法对比:哪种场景用哪种结构
查找这一章的知识点密度极高,必须先建立对比框架再逐个击破。我把常考查找方式整理成一张对照表。
| 查找方式 | 平均时间复杂度 | 前提条件 | 适用场景 |
|---|---|---|---|
| 顺序查找 | O(n) | 无 | 无序表 |
| 二分查找 | O(log n) | 有序且顺序存储 | 有序数组 |
| 二叉排序树 | O(log n) | 树平衡 | 动态查找 |
| AVL 树 | O(log n) | 严格平衡 | 频繁插入删除 |
| 哈希查找 | O(1) 平均 | 好的散列函数 | 等概率查找 |
| 分块查找 | O(log m + n/m) | 块间有序 | 静态+动态混合 |
| B 树/B+树 | O(log n) | 节点多路 | 数据库索引 |
这里必须强调二分查找的一个隐藏前提:除了有序,还要求顺序存储。链表即使有序也无法二分,因为无法通过下标随机访问中间元素。这个点在选择题里经常以「有序链表能否二分查找」的形式出现,答案是:不能。哈希表要注意装填因子与冲突的关系,装填因子 = 记录数 / 表长,装填因子越大冲突越多,平均查找长度越大。
5.2 八大排序算法:一张表记住复杂度与稳定性
排序是数据结构与算法里最值得花时间的章节,因为它的考题形式最丰富。八个常考排序算法的关键参数,我用下面这张表锁定。
| 排序算法 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|---|---|
| 直接插入排序 | O(n²) | O(n²) | O(1) | 稳定 |
| 希尔排序 | O(n^1.3) 左右 | O(n²) | O(1) | 不稳定 |
| 冒泡排序 | O(n²) | O(n²) | O(1) | 稳定 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | 不稳定 |
| 简单选择排序 | O(n²) | O(n²) | O(1) | 不稳定 |
| 堆排序 | O(n log n) | O(n log n) | O(1) | 不稳定 |
| 归并排序 | O(n log n) | O(n log n) | O(n) | 稳定 |
| 基数排序 | O(d(n+r)) | O(d(n+r)) | O(n+r) | 稳定 |
这张表要背到能随手默写的程度。额外要记住的结论有三条:第一,快速排序在序列基本有序时性能退化到 O(n²),平均性能最好;第二,堆排序和归并排序的最坏复杂度都是 O(n log n),是唯二能做到这一点的比较排序;第三,空间复杂度最小的排序是插入、冒泡、选择、堆排序,都是 O(1),而归并排序的 O(n) 空间是它的主要缺点。稳定性辨析题的常考场景是:「给一个排序算法过程序列,判断是哪种排序」以及「要求稳定排序时哪些不能用」。
5.3 快速排序手写模板与 partition 的边界处理
快速排序是算法设计题的第一热门。核心是 partition 操作:选一个基准值,把小于等于基准的放左边,大于基准的放右边,返回基准的最终位置。以下是最常考的 Lomuto 分区法实现。
def quick_sort(arr, low, high): """对 arr[low:high+1] 进行快速排序""" if low >= high: return pivot_index = partition(arr, low, high) quick_sort(arr, low, pivot_index - 1) quick_sort(arr, pivot_index + 1, high) def partition(arr, low, high): """以 arr[high] 为基准,返回基准最终下标""" pivot = arr[high] i = low - 1 # i 指向已处理区域中最后一个 <= pivot 的位置 for j in range(low, high): if arr[j] <= pivot: i += 1 arr[i], arr[j] = arr[j], arr[i] # 把基准放到正确位置 arr[i + 1], arr[high] = arr[high], arr[i + 1] return i + 1参数说明:arr 是待排序列表,low 是起始下标,high 是结束下标;递归终止条件是 low >= high,也就是只剩一个元素或区间非法。逻辑说明:i 初始为 low - 1,每找到一个小于等于 pivot 的元素就把 i 前移并交换,循环结束后 i + 1 就是基准应在的位置。考试手写时最容易错的点:一是退出条件写成 low > high 会漏掉单元素区间导致死循环,二是 partition 返回后的递归区间边界,必须写成 pivot_index - 1 和 pivot_index + 1,否则基准会重复参与排序进入死循环。这是整个排序章节里最常见的翻车现场。
5.4 堆排序的两个关键操作:下沉建堆与堆顶取出
堆排序的代码量大,但如果理解了下沉操作,整道题就通了。建堆过程:从最后一个非叶子节点开始,依次往前做下沉操作。下沉的含义是:当前节点与其左右孩子中较大的比较,如果当前节点小就交换,交换后继续下沉直到满足堆性质。取出堆顶后,把最后一个元素移到堆顶再下沉调整。
def heapify(arr, n, i): """对 arr[i] 做下沉调整,n 为堆大小""" largest = i left = 2 * i + 1 right = 2 * i + 2 if left < n and arr[left] > arr[largest]: largest = left if right < n and arr[right] > arr[largest]: largest = right if largest != i: arr[i], arr[largest] = arr[largest], arr[i] heapify(arr, n, largest) def heap_sort(arr): """堆排序:先建堆,再逐个取出堆顶""" n = len(arr) # 从最后一个非叶子节点开始建堆 for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i) # 逐个取出堆顶 for i in range(n - 1, 0, -1): arr[0], arr[i] = arr[i], arr[0] heapify(arr, i, 0)这段代码的要点:数组下标从 0 开始,所以节点 i 的左孩子是 2 * i + 1,右孩子是 2 * i + 2,最后一个非叶子节点下标是 n // 2 - 1。建堆循环从该下标递减到 0。取出堆顶后,堆的有效范围变成 i,所以 heapify 的第二个参数传 i 而不是 n。考场时间紧张时,只要能把建堆和调整两步写出来,就算没到满分也能拿到大部分步骤分。
6. 图与算法设计策略:大题怎么踩点得分
6.1 图的存储结构与遍历:邻接矩阵 vs 邻接表
图的算法设计题一般不会要求完整实现,更多是考察遍历序列和算法步骤。邻接矩阵适合稠密图,判断两点是否相邻是 O(1),但存储空间是 O(n²);邻接表适合稀疏图,存储空间是 O(n+e),但判断两点相邻需要遍历链表,平均 O(e/n)。DFS 用递归或栈,BFS 用队列。考试常出:给定一个图,写出从某个顶点出发的 DFS 和 BFS 遍历序列。注意 DFS 序列不唯一,取决于邻接点的访问顺序;BFS 序列在邻接矩阵和邻接表存储下也可能不同。
6.2 最小生成树与最短路径的步骤描述模板
Prim 算法和 Kruskal 算法是简答高频题。Prim 的核心步骤:从任意顶点开始,每次从「已在树中的顶点」与「不在树中的顶点」之间的边中选最小的一条加入树,重复 n-1 次。Kruskal 的核心步骤:把边按权值从小到大排序,每次选最小边,若加入后不形成回路则保留,直到选够 n-1 条边。这里的回路判断要用并查集,考试如果只考描述步骤,要知道怎么判断回路。最短路径的 Dijkstra 算法考概念居多,记住它的限制条件:不能处理负权边,贪心策略。答题时把「集合 S 表示已确定最短路径的顶点」「dist 数组存当前最短距离」写清楚,步骤分基本就稳了。
6.3 分治、贪心、动态规划的识别与适用边界
算法设计策略这部分,考试常给一个问题让你判断应该用哪种策略。分治的特征:问题能拆成独立子问题,例如归并排序、二分查找。贪心的特征:局部最优能推导全局最优,例如哈夫曼编码、Prim、Kruskal、Dijkstra。动态规划的特征:子问题重叠且有最优子结构,例如背包问题、最长公共子序列。一个简单的判别方法:如果子问题不独立,分治会重复计算,就该考虑动态规划;如果每一步只需要找当前最优且不会影响后续决策,就是贪心。考试常见陷阱是把 0-1 背包当贪心做——0-1 背包用贪心得不到最优解,但如果题目说物品可以分割,那才是贪心的适用范围。这个区别在很多备考笔记里都含糊带过,而考场上只要识别错策略,整道题就白写了。
7. 避坑指南:备考数据结构与算法最容易翻车的五个地方
7.1 时间复杂度记混:把平均和最坏当成一回事
现象:选择题问「快速排序在最坏情况下的时间复杂度」,有人选了 O(n log n),理由是「快排不是很快吗」。原因:这是典型的概念混淆,快排的平均复杂度确实是 O(n log n),但当每次 partition 都极端不平衡时,递归深度变成 n,总比较次数是 O(n²)。解决:背复杂度表时把「平均」「最坏」「最好」三列分开背,同时要能举出退化的例子。如果考试给出一个已经基本有序的数组,快排反而最慢,因为每次选的基准几乎都是最大或最小值,划分极度不均。
7.2 递归代码的终止条件写错导致栈溢出
现象:手写二叉树遍历或快排时,recurse 函数没有处理空节点或单元素区间,运行时直接 RecursionError 或段错误。原因:递归函数缺少「最小问题直接返回」的出口,或者快排 partition 返回后区间划分边界取错,导致无限递归。解决:写递归先写终止条件再写递归体,这是一个肌肉记忆问题。二叉树遍历统一用 if root is None: return;快排统一用 if low >= high: return,不要用 low > high,因为 low == high 时区间只有一个元素不需要再排。
7.3 循环队列判满判空条件互相混淆
现象:填空题让写循环队列的判满条件,写成了 front == rear。原因:判空和判满在直观上都是队首等于队尾,容易搞混。解决:牢记「牺牲一个存储单元」的约定,判空是 front == rear,判满是 (rear + 1) % MaxSize == front。这个约定要在脑袋里找到一个形象参照:队尾指针追上队首指针一步就是满,队首队尾重叠就是空。考试万一忘了公式,可以拿 MaxSize=4 的队列手动模拟一遍,很快就能推出来。
7.4 二叉排序树删除节点时只会删叶子
现象:简答题要求画出删除一个度为 2 的节点后的二叉排序树,直接把该节点摘掉导致树结构断裂。原因:只记得二叉排序树的基本删除逻辑,没有掌握三种删除情况的处理:叶子直接删;只有左子树或右子树时,用子树顶替;有左右子树时,用中序前驱(左子树中最右的节点)或中序后继(右子树中最左的节点)顶替。解决:第三种情况是考点,处理完还要保证顶替后仍满足二叉排序树性质。备考时把三种情况各画一遍,把顶替节点如何「接住」被删节点的左右子树画明白。
7.5 排序稳定性判断题答反
现象:问「简单选择排序是稳定排序吗」,回答「是」,理由是「选最小的放到前面看起来很稳定」。原因:稳定性判断不能靠感觉,要盯着交换操作看。简单选择排序每次选出最小元素与当前位置交换,如果相同关键字元素在交换过程中相对顺序被打乱,就是不稳定的。例如序列 [2a, 2b, 1],第一轮选出 1 与 2a 交换后变成 [1, 2b, 2a],2a 跑到了 2b 后面。解决:用「两个相同元素 + 第三个最小元素」的心智模型快速验证:一旦发生跨越式交换,稳定性就没了。快排同理,partition 中的交换是跨越式的,所以不稳定。而插入排序和冒泡排序只在相邻元素间交换,不会改变相同元素的相对顺序,所以稳定。
8. 冲刺阶段的复习节奏与一套高效的知识点吸收方法
进入考前冲刺阶段,效率比面面俱到更重要。我的习惯是把复习分成三个轮次压实。第一轮用两天时间过一遍文档里的概念表和复杂度对照表,只做「认知识点」的事——看到每个名词能说出它的定义、复杂度、是否稳定,说不出来的标记出来;第二轮用三天时间专项刷算法题,每天只练一个模块的代码,周日把快排、堆排、二叉树遍历、括号匹配四个模板各默写一遍,连续默对才算过关。到这一轮结束时,所有代码模板要达到「不看参考能完整写出并说清每一步在干什么」的程度。第三轮进入刷真题模式,每套真题计时完成,错题整理到错题本上。
这里分享一个我自己验证过的方法:把知识点总结文档当作「索引」而不是「教材」。第一次读的时候手里拿一支笔,遇到已经掌握的知识点画一条线,遇到模糊的知识点画一个问号,遇到完全不懂的画两个问号。第一遍过完后,只复习画了问号和双问号的内容,这样第二轮就能省下差不多一半时间。对于模糊知识点,我习惯用「讲给别人听」的方式验证——找一个同备考的同学,把哈夫曼编码的构造步骤或快排的 partition 逻辑讲一遍,讲的过程中卡住的地方就是理解还不透彻的地方,这些位置比任何标记都精准。这个方法在时间紧张时格外好用,因为它的效率比反复阅读高得多,每次只会暴露真正薄弱的那几个点。备考到后期,人的精力会明显下滑,我的建议是每天晚上用 20 分钟做一套知识点卡片自测,把常考公式和代码关键行写在卡片正面,背面写易错点,睡前随机抽十张快速过一遍。另外要特别提醒:考试现场如果遇到一道题卡住了,先标记跳过去,把后面能拿的分拿完再回头。这个考试的时间是真的紧张,我在模拟考时就吃过亏,一道图论题纠结了十五分钟,结果后面的排序手写题时间不够了,希望帮到你。
本文还有配套的精品资源,点击获取