没有任何前置说明,直接从二级标题开始。 ## 1. 从一次模拟考试说起:为什么我把线性代数和数据结构放在一起练
每年考试季,总有同学跑来问我:“线代和数据结构哪科更该花时间?”我的回答通常很直接:两科都得练,而且最好放在同一轮模拟里。这不是和稀泥,是因为这两门课在考察方式上恰好互补——线性代数考你对抽象规则的敏感度,数据结构考你对逻辑流程的掌控力,把二者塞进同一场练习,等于同时训练两种截然不同的思维肌肉,效率比单独刷高不少。
这次“大学院笔试模拟练习(10)”就是按这个思路设计的。整场练习覆盖了典型的线性代数题型和数据结构题型,难度贴近常见大学院入试的笔试风格,但又不是直接搬真题,而是把高频考点重新组合成一套混合卷。适合正在备考大学院、需要检验自己复习进度的同学,也适合那些“知识点都懂、一做题就卡壳”的人——这种症状多半是缺练,不是缺理解。
为什么要特意搞“模拟”而不是继续翻教材?因为考试是限时环境下的输出能力测试,和平时看书的输入状态完全不同。你在书上觉得“显然”的推导,到了考场上可能手一抖就漏掉符号;你在笔记里标了“重点”的算法,真让你十分钟手写出来,可能会有各种细节断裂。模拟练习的价值就是把这些问题提前暴露出来,让你在真正考试前有机会修正。
这篇文章不是标准答案的罗列,而是把练习(10)涉及的核心题型、解题思路和踩坑点完整拆开讲一遍。我会把每道题的考察意图说清楚,遇到容易出错的地方会额外强调,还会补上一些平时不会写在教材里的实操经验,比如怎么分配时间、怎么检查计算结果、怎么在写代码题时避免低级失误。无论你是刚开始准备,还是已经刷到第二轮、第三轮,这篇笔记都可以当作一个不错的自查清单。
2. 线性代数部分:从行列式到特征值的高频考法
2.1 行列式计算:不要一上来就展开,先观察结构
第(10)卷的线性代数第一问通常是行列式,难度中等偏基础。这一题的意义不在“难住你”,而是用来淘汰那些只会机械展开、不懂观察结构的人。
举个例子,某个行列式长这样:
| 1 a a a | | a 1 a a | | a a 1 a | | a a a 1 |如果老老实实按第一行展开,四阶算起来不算太痛苦,但算到最后大概率符号出错。正确做法是先看结构——这是标准的“对角线元素相同、其余元素相同”矩阵。处理思路是先将第2、3、4列都加到第1列,得到:
| 1+3a a a a | | 1+3a 1 a a | | 1+3a a 1 a | | 1+3a a a 1 |提取公因子1+3a,第1列变成全1,然后用第1行乘以-a加到其余各行,把后三行第1列消成0,最终得到下三角形式,行列式结果为(1+3a)(1-a)^3。
这个过程里有两个常被忽略的点:
- 提取公因子后别忘了要乘回最终结果里,很多人都摘出去了最后忘记乘。
- 第2行到第4行的处理顺序要固定,先消第2行,再用新第2行做参考去消第3行,思路才不会乱。
我练这个题目时习惯先在草稿纸上用一句话标出“加列→提因子→消元→下三角”,再把具体数字填进去。这样可以省掉大部分复查时间。
类似的结构还常见于“行和相等的矩阵”,处理手法基本都是先加列提取公因子,再继续消元。这类题考察的本质是“你是否能识别矩阵的结构特征”,因为很多题目不给提示,行列式直接摆在那儿,不观察就硬算往往会绕远。
2.2 矩阵的幂与对角化:验证条件比计算本身更重要
矩阵幂是大学院笔试里的常客,练习(10)中出现的是形如求A^n的问题。这类题有一个几乎固定的解题路径:计算特征值和特征向量→判断是否可对角化→写成A = P D P^{-1}→得到A^n = P D^n P^{-1}。
这里最关键的环节不是最后的乘法运算,而是判断矩阵是否可对角化。拿一个具体例子来说:
A = | 2 0 | | 0 2 |这是单位矩阵的2倍,特征值是二重根λ = 2,但几何重数也是2(特征子空间是整个二维平面),所以它可对角化。但如果是:
B = | 2 1 | | 0 2 |特征值同样是二重根λ = 2,可几何重数只有1(只有一个线性无关特征向量),因此B不可对角化。很多人只看了特征值就急着说“可对角化”,结果后面全盘皆错。
判断可对角化的标准其实一句话:每个特征值的几何重数等于代数重数。几何重数就是A - λI的零空间的维数,算起来相当于“解(A - λI)x = 0得到的基础解系个数”。代数重数是特征多项式中该根的重数。
如果遇到不可对角化的矩阵,那就要改用最小多项式或Jordan标准型的方法。但在一般大学院笔试里,能对角化的矩阵占多数,所以我的建议是:先算特征多项式,再看重根的特征向量个数,一路判断下来,不要跳步。
计算P和P^{-1}也是个容易出错的点。很多同学求逆矩阵喜欢用伴随矩阵法,可是三阶以上的伴随矩阵法计算量不比初等行变换小,反而更容易出错。我在模拟练习里强烈推荐用初等行变换[P | I] → [I | P^{-1}],虽然步骤多,但每一步都有清晰的操作规则,出错的概率低很多。如果对初等行变换不熟练,可以先用二阶矩阵练上十个,手熟了再往高阶走。
2.3 特征值问题的常见变形:对称矩阵与正交对角化
练习(10)里还夹了一道对称矩阵特征值的题,混合在别的题型中间,很多人一看到“实对称矩阵”就开始条件反射要正交对角化,但实际得分率并不高。原因在于题目不一定要求构造正交矩阵,有时候只要求判断特征值的范围,或者利用相似对角化求k次幂,所以读题时一定要看清具体要求。
实对称矩阵有个非常好的性质——特征值都是实数,且不同特征值对应的特征向量彼此正交。利用这一点,可以免去部分正交化步骤。比如已知某个对称矩阵的两个特征值λ1=1、λ2=4,并且已经求出λ=1的特征向量,那么求λ=4的特征向量时,可以直接令它与已知特征向量正交,进而解出未知的特征向量。这招比硬算A - 4I的基础解系有时更快。
不过要注意:实对称矩阵的“不同特征值特征向量正交”是定理保证的,但“同一特征值的多个特征向量”不一定正交,需要自己做Gram-Schmidt正交化。不要混淆这个前提。
在写解答步骤时,我习惯把特征值、特征向量、正交化后的向量、单位化后的向量分四行列出,方便复查。如果中间某一步的结果看起来“丑”(比如根号、分数很不规则),通常不是算错了,而是可能用的参考坐标系不对,检查一下是不是在正交化时漏掉了归一化因子。
2.4 线性方程组与秩:小问题里的大陷阱
线性代数部分不只考行列式和特征值,方程组与秩也是高频综合考点。练习(10)里以“判断含参数方程组是否有唯一解”的形式出现。这类题的核心思路是把增广矩阵化为行最简形,然后根据秩的情况分类讨论。
遇到过不少同学在参数讨论时漏情况。比如矩阵里有一个含k的表达式作分母,解的时候直接“因为分母不能为零,所以排除某个k”,这个操作本身没错,但之后往往忘了讨论分母为零的情形是否真的无解或无穷多解。正确做法是:把参数取特殊值之前先不消去含参的项,化简到阶梯形之后再按参数分类,每一步都要问自己:“这一步我对参数做了什么假设?”
举个极简例子,方程组:
x + y = 2 2x + ky = 4第二个方程减去2倍第一个方程得到(k-2)y = 0。如果直接说“当 k=2 时无解”,那就漏了“当 k≠2 时有唯一解 y=0, x=2”的情况;而实际上当 k=2 时,第二个方程变成0=0,无穷多解,不是无解。这种低级错误在考场上高发,就是因为下意识把“参数在分母”错误移植到了“参数在系数”。
模拟练习能暴露这类问题的原因在于限时状态下你会走最顺手的路,很难停下来细想参数假设。所以每次做完参数讨论的题,我都会在解得最后补一句“当某参数等于某值时,原方程组变成什么样”,再写对应的秩。只要补了这一句,答案的完整性立刻上一个档次。
3. 数据结构部分:算法设计题的读题与手写实现
3.1 链表操作题:先画图再动手,不要边想边写
数据结构笔试和线代题很大的不同在于,它是“用文字和伪代码表达过程”。练习(10)里有一道链表逆置的题,要求写函数实现单链表原地逆置,并且不能申请额外节点空间。这题本身不难,但每年都有人写错,原因几乎都指向同一个——上来就写代码,不在草稿纸上画节点关系。
单链表逆置的核心是三个指针:prev、curr、next。操作路径可以总结成四步:
- 保存当前节点的下一个节点
next = curr->next; - 把当前节点的指针转向
prev:curr->next = prev; - 移动
prev到curr:prev = curr; - 移动
curr到next:curr = next。
循环直到curr == NULL,最后把头指针指向prev。
我见过最多的错误是在第4步忘了用第1步保存的next,导致链表后半段丢失。这属于手滑,不是思路问题,但考试里手滑同样丢分。解决方法是画“初始状态 → 一次循环后 → 最终状态”三张图,写代码前花30秒钟把图画完,后面基本不会错。
还有一类链表题是“判断是否有环”,练习(10)没直接考,但它和逆置一样都是高频基础题。快慢指针法(Floyd判圈)说起来简单,但手写边界条件却经常出错。核心是快指针每次走两步,慢指针每次走一步,若二者相遇则说明有环;另一个常考题是找环的入口,需要数学推导,这个推导过程我建议自己推一遍,不要死记结论,因为笔试可能让你证明“为什么按某个方式移动能找到入口”。
3.2 栈与队列:括号匹配这类题的边界条件比你想的多
栈和队列在笔试中的出题形式通常比较抽象。练习(10)出现的是括号匹配判断问题:给定一个只含( ) [ ] { }的字符串,判断括号是否合法闭合。这道题如果是在代码编辑器里跑,几秒钟就能验证,但在纸上手写伪代码,很多人会漏掉“栈为空时遇到右括号”这种情况。
正确的设计思路是遍历每个字符:
- 如果是左括号,入栈;
- 如果是右括号,先检查栈是否为空。为空则直接返回不匹配;不为空则弹出栈顶,字符与当前右括号配对检查;
- 遍历结束后,栈若不为空,则说明有多余的左括号,也不匹配。
边界条件就三个:遍历中的空栈问题、配对不符问题、结尾非空问题。我习惯在写代码前用( [ ) ]、((()))、)(这三个例子分别走一遍逻辑,确认三种失败形式都能被抓住。
手写这道题时,伪代码的栈操作尽量写成push、pop、top、empty这样清晰的自解释接口,不要省略判断条件。阅卷老师看的就是你有没有考虑边界情况,把边界检查步骤显式写出来,比缩略写法更占便宜。
3.3 树:递归遍历的书写规范与层序遍历的手动队列
数据结构部分的树相关题是重头戏。练习(10)里有一道要求“写出二叉树前序遍历的非递归实现”的题。非递归前序遍历通常借助栈:先访问根节点,再把右孩子入栈,再处理左子树。伪代码大概是:
push(root) while stack not empty: node = pop() visit(node) if node->right != NULL: push(node->right) if node->left != NULL: push(node->left)这个写法里,入栈顺序是“先右后左”,因为栈是LIFO,先入右孩子才能保证左孩子先被访问。很多人写反成“先左后右”,遍历顺序就变成了根-右-左。
非递归中序和后序更麻烦,手写时容易出错。中序非递归的思路是:一路向左走,把沿途节点全部入栈,直到左子树为空,再弹栈访问,然后转向右子树。后序非递归通常用两个栈或标记法,技巧性更强。我的建议是:考前把前序、中序、后序遍历的非递归实现各手写一遍,做成模板记忆。笔试现场现推虽然也能推出来,但会消耗大量时间,不值得。
层序遍历出现频率也不低,经典工具是队列。每次出队一个节点就访问它,同时将其左右孩子入队。注意题目若要求“按层输出”,每层结束时需要额外记录层节点数,或者在当前队列大小范围内循环,以防把下一层节点混进同一层。这个细节是很多人的丢分点,模拟练习中我特意会在批改时标记出来。
3.4 排序与查找:手写快速排序时,枢轴选择和交换逻辑
排序算法在大学院笔试里不是让写最优代码,而是考察你是否理解算法的过程和稳定性。练习(10)里曾让手动模拟快速排序前两趟的过程,并写出基于“首元素为枢轴”的划分结果。这类题不算难,但手动模拟过程中非常容易抄错原数组。
快速排序的核心是划分操作(partition),常用的一种实现是“霍尔划分”:选一个枢轴值,从右往左找小于枢轴的数,从左往右找大于枢轴的数,然后交换。手写时必须注意指针移动的先后顺序,比如先移动右指针还是左指针会影响最终枢轴位置,也会影响算法的稳定性(快排本身不稳定,但不同写法会让不稳定表现不一样)。
考试时模拟快排,我建议按下面步骤操作:
- 先把数组索引标在草稿纸上;
- 每轮划分都用双指针标出当前
low与high的位置; - 每交换一次后在旁边记录本轮数组;
- 最终确定枢轴位置后,标记下一轮的子区间范围。
这样即使后面算错,也能比较方便地找出是第几步交换出了问题。之前遇到一个同学模拟快排时因漏写一个交换步骤,导致后续所有划分全都错位,检查半天才发现,白丢了十几分,非常可惜。
排序题还有一个常考知识点是“某排序算法是否稳定”。我习惯用这个概念强化记忆:稳定指“相同关键字的记录在排序前后相对次序不变”。选择排序、快排、堆排不稳定;冒泡、插入、归并、基数稳定。考试如果问“快速排序是否稳定”,答案是否定的,但最好能举个反例,比如[3, 2, 2]以第一个3为枢轴划分时,两个2的相对位置可能反转。写反例比干说结论更能得分。
4. 混合模拟的实战价值:一场练习同时检查两类思维漏洞
4.1 为什么要交叉出题而不是分开刷
很多人复习时习惯“上午两小时全做线代,下午两小时全做数据结构”,这种刷法有它的优点——注意力集中在单一知识域,短期内容易上手;但缺点也很明显:真实考试不一定给你这种“舒适区拆分”。
大学院笔试往往在教室里连着考,中间可能只有短暂休息,甚至两科在同一张卷上交替出现。脑袋在行列式和二叉树之间来回切换时,会产生额外的认知负担。练习(10)故意把线代和数据结构题穿插排列,就是为了模拟这种切换感。我第一次这么练时,切到第三题时明显感觉到思维有点“卡”,那正是平时分科刷题练不出来的体验。多来几次交叉模拟,考试的切换负担就会小很多。
交叉出题还方便对照检查自己的强弱项。比如同样一个小时内,线代部分算得顺但数据结构大题久攻不下,就能因此定位到“逻辑建模能力偏弱”,而不是笼统的“学得不好”。这种定位对后续复习方向非常有价值。
4.2 限时训练的价值:时间分配是笔试里的隐藏科目
大学院笔试的时间通常按“题量×难度”设定,不会给太多富裕。练习(10)的完成时间我建议按“线代50分钟 + 数据结构60分钟 + 检查10分钟”来安排,整体控制在两小时以内。具体到单题,先算作弊级建议:每道线代计算题最多花8分钟,超过就先跳;每道数据结构写码题最多花12分钟,超过也要先收尾。这个时间比不是标准,但很适合用来发现自己是否在某一题上钻牛角尖。
限时做题和平时练习最大的区别在于“时间压力下的选择”——你必须在“再想一会儿”和“先做下一题”之间做决策。经常有人在同一道题上耗掉20分钟,后面简单题没时间写,非常吃亏。我的经验是,草稿纸上做标记:题目旁边写“5min”,如果5分钟到了还理不出头绪,就标个圈,先做别的,最后再回头。事实证明,冷静下来之后再看的成功率比死磕高得多。
4.3 错题复盘的关键:不是看答案,而是还原思路断点
模拟练习做完后的复盘,比练习本身更重要。但复盘千万不要只看“这题正确答案是什么”,而要看“我当时思路在哪一步断了”。
我自己习惯用“断点记录法”:解题过程中,在草稿纸的某一角写下每道题卡壳的地方,比如“行列式加列法没想到”“链表逆置时没保存 next”“递归遍历时搞错了入栈顺序”等。做完后翻开这些断点,逐条对应到知识点,能明显看出错误集中在哪个环节。
比如做练习(10)有一道线性方程组参数讨论的题,我最初答案少讨论了一个参数情况。回看草稿,发现我在消元时用了一个“两边同时除以含参多项式”的操作,等于默认了该多项式不为零,等于在题干之外额外加了一个假设。这就是典型的“思路断点”——不是不懂秩的判断,而是消元时偷懒导致的假设丢失。找到断点后,我把所有“除以含参表达式”的操作都强制改写为“提取公因式但不约分”,后续再遇到参数题就没犯过类似错误。
错题复盘切忌把所有错因归结于“粗心”。一旦归结为粗心,就不会深入思考底层思维方式的问题,下次换个题目照样错。宁可把粗心拆成“看漏条件”“抄错数字”“忘记分类”“边界没检查”等具体类型,然后针对每种类型想一个对策,复盘的效益才会最大化。
5. 实操心得:从几十场模拟练习里总结的提分细节
5.1 从排版开始练:卷面影响的不只是印象分
笔试答题纸上的空间有限,很多同学喜欢把步骤写得很紧凑,一行接一行,结果后面发现某一步需要补充或者改正时,根本没地方下笔。我练过一段时间之后发现,最好的排版方式是“一题一区域,每行一个等式”,计算类题目用横线把推导过程整齐列出来,每一步之间空两行,方便检查和更正。
尤其是线性代数的矩阵变换,每一行都应写出“做了什么操作”,比如在行首标注“第2行减去第1行的2倍”。这一步不只能帮批改者看思路,更重要的是帮你自己在复查时快速定位。考试时如果时间紧张,不需要写完整注释,但可以用简单的箭头和短线标明,效果类似。
数据结构的手写代码也要注意格式。我见过有人从纸的左上角开始写,写到右边线再折回,最后整个函数如同乱麻,阅卷人很难看清层次。建议先用尺子或目测留出左侧1厘米的空白,然后严格缩格,函数体内的语句统一缩进两格,嵌套时再增加缩进。这样即使代码有小错,整体结构清晰,也比较容易拿到过程分。
5.2 检查环节的固定动作:用特殊值检验计算结果
考试最后10分钟检查时,不要漫无目的地重做一遍。我给自己规定了一套固定动作,非常有效:
- 线代部分:对求出的特征值,找一个对应特征向量带回去算
A v,看是否等于λv;对矩阵幂,取n=1代回验证;对行列式,把某个比较整齐的数值(如0或1)代入原行列式,看结果是否一致。 - 数据结构部分:给伪代码代入一个小型测试数据,比如链表
[1,2,3]、树只有三个节点,走一遍循环,检查每一步是否符合预期。
这些特殊值验证虽然不能保证100%准确,但能拦住绝大多数由于抄写、符号、索引越界引发的问题。练习(10)的模拟里,很多人特征值算对了但在矩阵A v验证环节发现向量符号写反,这类错误一抓一个准。
5.3 临考状态调整:两科之间的思维切换需要刻意练习
很多人忽略的一个事实是:不同科目之间切换时的“换挡”损耗是真实存在的。线性代数重计算、重符号处理,数据结构重逻辑、重伪代码表达,两种模式在脑区的切换需要时间。如果你每周末只做一套混合模拟,考前突然面对两科交替的真题,可能会觉得“脑子转不过来”。
因此我建议在考前两周内,每周至少做两次混合模拟,并且让自己的做题顺序和真实考试保持一致。比如真实考试的线代在前,那你模拟时也就先做线代;如果数据结构在前,那就先做数据结构。不要每次都从自己擅长的科目开始,因为到了考场上你没法选择顺序。这样的刻意练习虽然看起来只是“换了个顺序”,但确实能有效减少临场的思维切换焦虑。
另一个小技巧是:每完成一个科目的题目,在答题纸上做一个明显的分隔标记,比如画一条横线,写“以下为数据结构部分”。这不仅方便阅卷人,也能给自己心理上的闭合信号——“线代部分结束了,接下来换挡到数据结构模式”,减少上一科题目给自己带来的后续纠结。
5.4 常见低级错误速查表:考前过一遍能避掉一半坑
我把模拟练习中常见的低级错误整理成了一份速查表,每次开考前几分钟扫一眼,效果很好。这里分享出来:
| 错误类型 | 典型场景 | 对策 |
|---|---|---|
| 行列式提取公因子忘记乘回 | 提了1+3a后直接写结果 | 在草稿上把提取项圈出来,最后一步完成后再乘回 |
| 可对角化判断只看重根不看特征向量个数 | 特征值二重根就写可对角化 | 解(A-λI)x=0,数基础解系个数与重数比较 |
| 矩阵求逆用伴随法算错代数余子式符号 | 三阶以上伴随法出错率高 | 优先用初等行变换[A|I] |
| 参数方程组默认分母非零 | 消元时两边除以含参表达式 | 改写成“若 k=…… 则特殊处理”的格式 |
| 链表逆置忘保存 next 指针 | 循环里顺序写反,断链 | 先画三步状态图再写代码 |
| 括号匹配忽略空栈 | 遇到右括号直接 pop | 先检查empty()再 pop |
| 二叉树非递归遍历入栈顺序写反 | 前序入栈写成“先左后右” | 记住“先右后左”,出错时用三节点树自测 |
| 快速排序模拟时指针移动顺序出错 | 左右指针越界 | 在草稿上标注每一轮low/high当前值 |
| 代码缩进混乱 | 手写代码层次不清 | 预留左侧空白,统一缩进规则 |
| 草稿与答卷分离 | 答案写错位置 | 每题答题区域固定,写完即核对题号 |
这份表不一定覆盖所有学校的所有题型,但应对大多数“大而基础”的大学院笔试已经足够。我每次做新模拟卷时,都会把新遇到的问题往表里加,越补越全,到最后基本不会再犯重复的低级错误。
6. 个人体会:模拟练习(10)做完之后,我更看重什么
这道混合模拟练习第10套做完,我自己最大的收获不是多会了几道题,而是认清了一个事实:刷题也好,复习也罢,最终要训练的是“在有限时间内稳定输出已有知识”的能力。懂和会写之间,隔着一整个模拟练习的距离。
所以如果你现在还在为大学院笔试焦虑,与其再翻一遍笔记,不如腾出两个小时,正经做一套混合模拟,尽可能还原考场状态。做完之后认真复盘自己的思路断点,找出那些导致失分的“隐藏假设”和“边角边界”,再针对性地修正。按这个节奏练上几套,你对时间和正确率的控制能力会比盲目刷题提升得更明显。
最后分享一个我一直在用的细节习惯:每次模拟练习结束后,在卷子首页空白处写三行字——第一行写这次练习的目标,第二行写实际完成情况,第三行写下次最需要改进的一个点。别小看这三行字,它对后续复习方向的调整帮助比我预期的还要大。下一次做模拟时,把上一轮的三行字拿出来对比,你会明显看到自己的变化。这就是我眼中模拟练习最大的价值所在。