ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

东华复试OJ机试刷题复盘:每日3题打卡与算法模板总结

东华复试OJ机试刷题复盘:每日3题打卡与算法模板总结 东华复试的机房我断断续续刷了四十多天每天雷打不动三道题做完顺手在打卡表上画个勾。这个习惯谈不上多高级但确实把我从“看一眼答案觉得会了”的假把式里拽了出来。尤其是第13到15天的复盘是我整个准备期里状态最典型的一个小周期题型开始从纯数据结构往综合题过渡人也从机械做题慢慢摸出了门道。这篇文章没有太多玄乎的技巧就是一个过来人把这三天的题目、踩过的坑、排查方式和工作原理录下来。目标是帮那些正在准备东华复试机试、或者打算用OJ练手的朋友建立一套自己的做题节奏。如果你还在靠感觉刷题看完应该能调整出更省力的路线。1. 为什么我要做复试OJ每日3题打卡1.1 东华复试的机试到底在考什么东华大学计算机相关专业的复试机试很多年都沿用OJ在线判题模式。它跟本科上课时的实验题不一样限时、限环境、代码必须一次成型。网上有人把它类比成“现场写算法笔试”这个说法其实不太准确它更像“现场跑代码”不仅要写对还要在给定时间和内存内通过全部测试点。复试机试一般集中在基础数据结构和经典算法链表、二叉树、栈、队列、图论入门、字符串处理、简单动态规划这些是绝对主力。题型不会往ACM金牌题那个方向卷但很多同学容易栽在细节上输入输出格式对不上、全局变量初始化漏了、递归深度爆栈、用了C11之后才有的特性结果编译器不认。这些问题我在第13~15天里基本碰了个遍。做OJ是被动接受测试你不知道测试点长什么样只能从错误反馈里猜。这种“猜”的能力并不是玄学它来源于对数据范围和边界条件的敏感度。每天的3题打卡本质就是在训练这种敏感度。1.2 每日3题的选题策略与打卡机制我的打卡规则很简单每天3题一题巩固旧知识点一题做新知识点的经典题一题从错题本里重做。选题来源不限于东华OJ杭电OJ、东方博宜的一些经典题我也会拿来混着练。原因很直接复试机试不指定题库光刷一家平台的题容易形成思维定式。打卡表长什么样就是一张Excel三列日期、题号/题目名、复盘要点。做完在日期后面打勾错了就标红写一句为什么错。这听起来有点刻板但它解决了最大的问题你没法用“今天忙没时间”来骗自己。每天3题花不了90分钟15分钟一题中间休息十分钟比打开视频看两小时题解有用得多。第13~15天我更刻意地做了调整不再碰那种一看就会的模板题把重心挪到需要梳理边界条件的综合题上。事实证明这个调整很及时因为三月到四月的复试冲刺期最缺的不是新知识而是把旧知识组合起来用的手感。2. 第13~15天九道题逐一复盘2.1 第13天链表的三个经典动作第13天做的是三道链表题反转链表、找倒数第k个节点、找两个链表的第一个公共节点。这三道题属于复试高频题我不止一次看到有人抽到类似的变体。反转链表是入门题但它值得用两种方式写一遍迭代和递归。迭代写法需要三个指针prev、cur、next依次翻转方向。很多教程会画指针箭头但实际写出来最常见的问题是while循环里漏了prev移动。递归写法反倒不容易漏因为递归天然有回溯但是递归的返回值设计容易翻车返回的是新头而不是当前节点。找倒数第k个节点用快慢指针快指针先走k步然后两个指针同步走。这里有个隐藏考点如果k比链表长度还大要在快指针走完之前做判空。不少同学用vector存节点然后按下标取值虽然能过但面试时如果问时间复杂度O(n)空间和O(1)空间还是有差别的。找公共节点那道题经典的“走过你来时的路”解法确实巧妙两个指针分别从两个链表头出发走完自己的链转向对方的链最终会在公共节点相遇。这个解法我第一次看没懂为什么后来想明白了两个指针走的总路程相等都是lenA lenB而公共部分肯定在最后。第13天我特意把这道题重写了一遍因为之前只记结论没推导过正确性复试面试官最喜欢在这个地方追问。实话说这天的3题都偏基础但我花了不少时间在推导上尤其是公共节点那道题我把“为什么会相遇”推导了一遍假设链表A的长度是acc是公共段链表B是bc两个指针最终都走了abc步。这样就算没有公共节点它们也会同时走到null不会死循环。这个推导在纸上写一遍比看十遍题解都有用。2.2 第14天树与图的遍历思维切换第14天难度抬了一档二叉树最大深度、二叉树层序遍历、无向图连通分量个数。前两道题是树的遍历模板题第三道是从树到图的思维跳跃点。二叉树最大深度递归见顶即返的思路没什么好讲的。但我把它扩展成了非递归版本用层序遍历记录层数。这个扩展不是多此一举复试机试经常把“最大深度”包装成“最小深度”一旦用递归写最小深度就会碰到一个非常隐蔽的坑如果一个节点只有一个孩子空孩子那一侧不应该参与min计算很多人在这里采坑。层序遍历那道题标准做法是队列BFS每层开头记录当前队列长度然后只弹出这么多个节点。这个“固定层长”的细节很关键如果不固定就会把下一层的节点也弹出来错乱层边界。第14天我在这道题上纠结了挺久因为我一开始用的是每次弹一个节点就处理一个最后发现和二层的顺序对不上。无向图连通分量个数这道题我做的是DFS染色版遍历所有节点遇到没访问过的就给它染一个新颜色然后从这个节点开始DFS把同连通块的节点都标记掉。统计染了几种颜色就是答案。这道题倒是不难但它逼我复盘了一个老问题递归DFS在节点多的时候容易爆栈坚持用递归还是改栈东华OJ的评测机栈空间不算大如果图有几十万节点递归就不稳了。稳妥起见我练了两版一版递归一版手动栈。手动栈其实就是模拟DFS的压栈过程区别在是否显式维护一个stack容器。写起来并不复杂但要注意压栈和访问标记的顺序入栈前标记还是在出栈时标记。入栈前标记可以防止重复入栈出栈时标记则可能让同一个节点被压进去多次。这两种写法在判题上都会产生差异测试点多的时候差异会放大成WA或MLE。2.3 第15天字符串、大数与模拟题的组合拳第15天的题目是三个方向字符串第一个唯一字符、两个大数相加、约瑟夫问题。这三道题看起来各干各的实际上它们有一个共同点都要在“最基本的操作”上扣细节。字符串第一个唯一字符最简单是哈希计数两趟扫描解决问题。第一趟统计每个字符出现次数第二趟按字符串顺序找第一个计数为1的字符。这道题时间复杂度O(n)空间O(1)因为字符集大小固定。复试极少考那种需要后缀数组的题目但会对空间复杂度吹毛求疵。大数相加那道题是字符串模拟从个位对齐逐位相加维护进位。核心全在循环结束后的进位判断上。我一开始写的就是循环结束忘考虑进位结果999加1返回了990WA得很冤。后来固定写三步反转短串补零、逐位相加、循环外处理最高位进位。这里有个细节字符串模拟加减法delete两行代码就可以写出让人看不太懂的bug不是一个好习惯的说不清。约瑟夫问题属于经典模拟环形链表是最直观的解法但数据量一大就超时。第15天我顺手复习了数学递推法f(1)0f(n)(f(n-1)m)%n最后结果是f(n)1。这个递推为什么能省时间因为它把每一轮“报数”的删除过程压缩成了一个取模运算跳过了一步步移动指针的开销。三道题做完我发现当天它们其实是同一个主题抽象理解基本操作。唯一字符是哈希的抽象大数相加是进位的抽象约瑟夫是删除动作的抽象。这种主题归纳是复盘的核心价值题目在变解法骨架不变。3. 从这9道题里沉淀出的通用解法模板3.1 链表题的“双指针”直觉从哪来第13天的三道题本质上都用了双指针思维反转链表是三个针互相协作倒数第k个是快慢速度差公共节点是路程差转相遇。这个直觉的来源是把链表当作一个“只能单向走”的结构。一旦不能回退双指针就是在有限信息条件下拉出距离差和位置差的万能手段。我在复试准备期把所有链表题都归了个类删除类虚拟头节点前驱指针、找位置类快慢指针、重排类反转合并。分类之后遇到新题先套类再想细节思路就快很多。假如你刷题时觉得每道链表题都是新题大概率是因为你没有建立这个分类框架。链表题的另一个通用模板是哑节点dummy head。带头节点的链表操作少了很多判空逻辑但很多学生习惯用不带头节点的写法然后发现删除头节点时总得特判。我自己的习惯是除非题目明确不给额外空间一律先建哑节点把头节点当普通节点处理。这个小习惯让我少踩了很多空指针的坑。3.2 BFS/DFS的适用边界怎么判断第14天同时写了两者正好可以做个对比。BFS是按层扩散天然适合找最短路径圈和连通块遍历DFS是沿路径深入适合判定可达性、路径存在与否、回溯枚举。但在复试OJ里它们经常可以互换统计连通分量个数BFS和DFS都能写关键看哪种不爆栈。我的判断标准很简单如果题目里的“步数”或者“距离”有意义优先BFS如果只是问“能不能到达”或者“共几块”DFS更省事。但是当节点总数超过一万我一般会主动把手写递归改成显式栈或队列的BFS。东华复试的评测机栈空间我没具体测过但与其赌递归深度不如直接上迭代版本保险永远大于侥幸。这里多提醒一句BFS的最短路径有个前提就是边长相同。如果边长不一样BFS求得的最短步数不等于最短距离这时候得用优先队列Dijkstra。很多同学把BFS当成无敌的最短路刷到带权图就翻车。第14天我把这个前提写在了错题本里因为第13天的教训告诉我结论比代码更容易被遗忘。3.3 模拟题的边界检查到底查什么模拟题最容易挂的地方不是主逻辑是边界。大数相加的进位、约瑟夫的取模起点、层序遍历的层边界都是同一种东西循环后的残留状态。我的检查顺序固定分四步空输入、最小输入、最大输入、连续操作。用大数相加来看——空输入就是空字符串最小输入是“00”最大输入是int边界的数值或超长字符串连续操作是“999……1”看进位是否层层传递。这套检查顺序我在所有模拟题上都用已经形成了肌肉记忆。这四步检查还有一个好处它不是凭空想的而是根据数据范围推出来的。复盘第15天时我在打卡表里写了一句边界检查不是猜测试点是把题目的输入范围离散成几类想想每类的最坏情况长什么样。这句话后来救了我好几次。4. 复试OJ刷题避坑指南4.1 编译环境与输入输出差异复试OJ最恶心的不是题目难而是环境差异。同一个代码在本地跑得欢提交上去就是CE编译错误。东华的评测机环境每年不一定完全一样从学长学姐反馈来看C基本是支持C11的但有些较新的特性不一定稳定。我的策略很土但很有效统一写成C98/11都能编译的代码避免C14、17特性比如auto作为变量类型我尽量少用除非一眼能确定类型。输入输出上的大坑是ios::sync_with_stdio(false)。这行代码确实能提速但它和scanf、printf混用时会出问题。一旦开启了同步关闭再用printf输出就可能导致顺序错乱。我在第13天就干过这事本地测试输出正常OJ上直接WA排查了十分钟才想起来是混用了。从那以后我坚持一套方案要么全用cin/cout并且关闭同步要么全用scanf/printf绝不混用。4.2 超时与内存超限的排查顺序第14天我碰到过一个TLE超时让我复盘了很久。当时我用递归DFS统计连通分量数据量一大就超时然后我把递归改成了非递归用显式栈模拟但还是超时。最后发现问题不在DFS本身而是我用了map来标记节点访问状态每次查找O(log n)累积起来就拉了时长。换成vector 数组后瞬间快了。这个教训让我总结了一个排查顺序先看算法复杂度是否匹配数据范围再看有没有不必要的对数或常数类型操作最后看输入输出是否太慢。“每次都少跑一个循环”这类微优化收效不大改掉一个log级别结构才是治本。你在OJ上看到的那种别人AC用时是你的四分之一多半不是人家代码藏了什么巧思而是少做了一个map查找。内存超限MLE也比较常见往往是数组开得太大方。一般来说动态分配的vector比固定大数组更省心因为它是按需分配不用的空间不占内存。但这个说法并不绝对如果你提前知道最大数据范围直接开一个刚好能装下的静态数组反而更快。4.3 打卡坚持策略我从连续43天里学到的连续打卡43天说实话中间想过放弃尤其是第15天连续三天碰到综合题做题节奏被打乱挫败感很强。我用的办法是“降低单日预期不降低出场频率”状态好的时候多刷几题状态差的时候哪怕只写一分钟的思路也要打卡。形式上可以缩水但不能断。打卡表里我会记录“错因标签”比如注意力不集中、边界没考虑、数据结构选择失误。第14天的层序遍历错在边界第15天的大数相加错在进位残留这些标签积累多了就会发现自己犯的错总是集中于几个类型。这时候针对性地去练效率会翻倍而不是像一个无头苍蝇一样到处乱撞。如果你也用打卡表我建议加一列“这道题让我想起哪道题”。复盘第15天的约瑟夫问题时我写的是“让我想起链表删除那道题”这种联想记忆比孤立记题牢固得多。考试时可以借着这个联想顺藤摸瓜快速定位解法。5. 东华OJ与常见OJ平台的差异5.1 和杭电OJ、郑轻OJ、东方博宜OJ有什么不同很多同学从杭电OJ、郑州轻工业大学OJ或东方博宜OJ入手刷题这些平台题库大、用户多确实是练习好去处。但东华复试OJ的体验差别比较明显题量少、偏基础、测试点设计得更狠。简单说它可以当作“检测能力基线”的工具不适宜当成练习的主战场。杭电OJ的题很多是ACM原题难度梯度陡刷起来容易上头。郑轻OJ的题目贴近校内教学适合刚入门时刷。东方博宜OJ体系感强按知识点分得很细适合按图索骥系统刷。但东华复试OJ更像“期末考试版”题少而精每道题都卡边界条件。你在这个平台上AC一道题意义不亚于在杭电上AC三道同难度题。还有一个现实情况东华复试OJ的界面和判题反馈都比较简单没有太多样例提示所以做题时自测就显得特别重要。我习惯先用本地IDE写个对拍程序生成随机数据比对暴力解和高效解的输出确认无误再粘贴提交。另一个平台的题刷多了这一套流程会生疏这一点值得注意。5.2 复试机试的评分逻辑与应对复试机试的评分一般不是只看对错时间复杂度和代码风格也可能被纳入考量。虽然机器判定主要看通过率但复试面试官会调代码来看如果你的代码命名清晰、变量名有意义、有基本的注释印象分会完全不一样。这是我参加模拟复试时一个老师说漏嘴的后来我在正式机试和面试环节都特别注意这一点。我的应对策略先把暴力解写出来拿到部分分再优化AC。不要在第一时间憋最优解因为时间有限暴力解至少能保底。一旦过了全部测试点再回去优化也不迟。这个“先保底再优化”的节奏我在复盘第13~15天时反复检验过确实能把慌乱感降到一个可接受的水平。关于代码注释我不建议写大段中文注释但关键逻辑两三句还是需要的。面试官看代码时如果你的注释正好交代了算法核心他能快速看懂你的思路也能避免“这段代码是不是抄的”的质疑。加上命名规则不要用a、b、c这种无意义变量用left、right、cur、dist这类有语义的命名整体观感会好很多。很多人会问复试OJ要不要刷难题我的答案是不用但要把简单题做深。链表反转不值得花太多时间去刷它的迭代和递归两种写法吗值得因为面试可能问的就是底层反转过程。层序遍历值得写BFS和DFS两种版本吗值得因为考察点的本质是你能不能用两种视角解决同一个问题。深度永远比数量重要这是我四十多天打卡攒下的最大心得。6. 一些实操中的锦上添花手段6.1 用“先手动跑样例”代替盲写第13天开始我养成了一个习惯看到题目先不写代码拿题目给的样例在纸上手动模拟两遍把流程跑通再动手。这个过程看似浪费时间但我发现它能提前暴露边界问题比如我手动模拟约瑟夫问题时模拟到第6个人就意识到取模的起点会偏一位于是写代码时直接加了偏移量。复试机试时间有限很多人不愿在纸上花时间直接上手敲。但我观察到的结果是直接敲代码的人要么一遍过样例然后卡在隐藏测试点要么改来改去浪费更多时间。手动模拟样例不是画蛇添足它是最廉价的对拍工具。6.2 错题本的另一个隐藏用法错题本不是用来“存”错题的是用来“找规律”的。每道错题我除了写原因还会标注是在哪个环节错的。第14天层序遍历卷错了“层边界”第15天大数相加卷错了“循环后状态”汇总后我发现我的错误大多是“操作终止条件”和“操作延续状态”混淆。这个规律让我后来的复习有了重心不再平均用力。如果你发现你的错题大多集中在某个环节比如输入解析或者初始化那你就该针对性地刷那一类题目而不是又从第一题开始顺下去。错题本对复习的指引价值比记录价值重要得多。我甚至敢说能把错题本用活的人刷题效率至少翻一倍。6.3 第一次遇到陌生题型的应对心态第15天虽然是复盘周期最后一天但里面遇到的题没有一道是“看一眼就知道解法”的。大数相加要现场手写进位逻辑约瑟夫问题要决定用什么数据结构这种心态上的考验比代码能力更大。我的办法是先接受“可能写不出最优解”的事实然后逼自己15分钟内写一版能跑通常规测试点的代码拿到分数再谈优化。这个心态在复试当天也很有用。真遇到没见过的题型第一反应不是慌而是把题目翻译成你熟悉的模型——字符串题翻译成哈希或双指针图论题翻译成BFS/DFS/Dijkstra套件。翻译得越熟练临场发挥越稳。我复试那天的机试题目不算难但有一道题我一开始没识别出是并查集翻译成图连通分量后用DFS也过了。所以说知识储备够用的情况下识别模型的能力才是拿分的关键。写在最后第13~15天的复盘写到这里其实有点像一个节点的收束从最初的读题猜解法到现在的读题先手动模拟再翻译成模型最后检查边界和复杂度。这个过程不惊艳但是可复制。如果你也在准备东华复试或其他学校的机试我建议你坚持“每日3题打卡”这个笨办法坚持半个月你就会发现错题类型开始重复解法开始形成肌肉记忆。有一点我想特别提醒不要迷信题量而忽略复盘。我认识一个同学刷了三百多题但问他每种题型解决的核心是什么他答不上来。刷题的意义在于形成稳定的解题结构而不是在OJ上留下一条漂亮的提交记录。如果你能把每一道题精做成“一道顶三道”的深度即使只刷一百题复试机试也足够从容了。最后把我打卡表里那条写了三期的话放在这里节奏比爆发重要复盘比进度重要错因比分数重要。复试不是一个拼天赋的关卡它拼的是你有没有把每一个简单模型吃透。共勉。
返回列表