2024年秋招我也加入了投递大军印象最深的还是蚂蚁集团工程研发岗的第二批笔试。整个批次做下来最大的感受是这场笔试考的其实不是你有没有刷过某道题而是你在有限时间内怎么拆解问题、怎么写代码、怎么处理边界条件。工程研发岗的定位也决定了它的题目不会像算法岗那样偏竞赛但代码量、细节量一点不轻对“能不能写干净代码”的要求反而更高。这篇文章没有具体题目答案主要是从我自己的视角复盘一下这批笔试的题型方向、我踩过的坑、客观题覆盖范围以及考后怎么把这次笔试转化成后续面试的素材。无论你是明年准备秋招还是正在等面试通知都希望能有点帮助。1. 笔试整体情况批次、时间、题型与平台特点1.1 考试基本信息与入场流程第二批笔试安排在某天的晚上时长大概是两小时左右具体时间以邮件通知为准。考试用的是牛客网在线笔试系统需要提前一些时间进入等待页面入场的时候要做环境检测包括摄像头、麦克风、屏幕共享权限有些场次还会要求用手机扫一个码做副机位监考。整体流程和国内其他大厂的在线笔试差不多入场阶段会比想象中更耗时间建议至少提前30分钟开始调试。我当时遇到的一个小插曲是浏览器权限弹窗没有提前放行进入考试页的时候摄像头一直加载不出来折腾了大概五分钟才通过检测。这个阶段看起来无关紧要但实际会消耗你的心态和考试时间所以提前把浏览器权限、网络、充电、草稿纸都准备好比多刷一道题管用得多。考试说明里一般会写明可以自备草稿纸和白板笔但有些场次要求考前对着摄像头展示草稿纸正反面均为空白不能切出考试页面切出会有次数记录。这些规则每个批次不完全一样以当次通知为准但我建议统一的策略就是按照最严格的标准准备防止无意中触发违规提醒。1.2 题型构成和难度梯度我拿到的试卷结构是编程题加客观题混合客观题以选择题为主放在整套卷子的靠前位置编程题大约四道分布在客观题之后。客观题分值不大但胜在数量不少涵盖了数据结构、数据库、计算机网络、操作系统、Java基础、多线程等内容覆盖范围很广。编程题的难度梯度比较明显基本可以分成四档第一档是规则模拟题审题清楚、直接按逻辑写就能做出来属于“签到题”。第二档是动态规划状态转移方程不复杂但边界和取模细节容易出问题。第三档是图论或者搜索变体需要一些建模能力我印象里是一道和带权边最短路相关的问题。第四档是数据结构优化题典型套路是“暴力能过一部分数据但想全过必须用线段树、树状数组或者堆做优化”。这种梯度设置本身就是在做筛选第一题看你的基本代码能力第二题看你的状态抽象能力第三题看你的临场建模能力第四题看你的工程优化意识。对于工程研发岗来说这种考察维度和实际工作中“先实现、再优化、再考虑边界”的节奏是吻合的。1.3 从题目看工程研发岗位的能力要求考完之后我回看整张卷子发现它并不追求让你当场发明一个高深算法而是考察代码习惯和工程思维。举个例子模拟题虽然简单但有大量如果条件判断如果变量命名混乱、分支嵌套太深写起来非常容易出错优化题虽然需要数据结构但更关键的是你能不能在读懂题目之后快速判断出复杂度瓶颈在哪里。工程研发岗的日常开发里很多时候并不是大家不会算法而是拿到需求后缺少“先拆解、再设计、再编码”的习惯。这次笔试给我的感觉就是在模拟这个流程题目都给了一个相对具象的业务背景需要你把它抽象成数组、图或者区间上的问题再用代码落地。2. 四道编程题的方向复盘与思路拆解2.1 第一题规则模拟题——审题和边界值才是得分点第一题属于典型的高频签到题我的印象是它给了一个操作序列要求按规则对某个数组或者字符串做处理。这种题在算法上没有门槛真正杀死人的是“没看清规则”和“边界值没想到”。我当时采取的流程是先不急着写代码而是把规则一条条列在草稿纸上比如操作有哪几种类型、每种操作什么时候生效、如果输入为空怎么办、如果数组长度只有1怎么办。列完之后再动手代码会清晰很多。一个常见的边界例子是这样的如果要求把数组下标从1开始计数而你写循环时用了0基最终答案在边界附近就会错。我习惯在写完主逻辑之后手动构造几个最小用例长度为1、全相同元素、最大范围值再跑一遍。这种题不建议追求特别精巧的写法用最直白的方式实现就好。笔试环境里可读性比“一行流”重要得多就算后面有bug至少评委和面试官看得出来你的逻辑。2.2 第二题动态规划——状态定义比转移方程更重要第二题是一道动态规划。我复盘时觉得这类题最关键的不是转移方程本身而是能不能在几分钟内找到一个“不重不漏”的状态定义。状态定义对了转移是顺水推舟状态定义错了后面会越写越乱。我当时遇到的题目大致可以抽象成一个“选择与收益”的问题有一系列操作你可以选择执行或者跳过但有一些约束条件最后要求最大化某种收益。这种类型的通用状态设计思路是用dp[i]表示处理到第i个元素时的某个最优值然后用两层循环去枚举上一个状态。如果内存比较紧张常见处理方式是用滚动数组把二维dp降成一维类似背包问题的空间优化。我在笔试里没有选择滚动数组因为担心边界写错直接用二维数组保存了所有状态好在这道题的范围没有大到内存不够。有一个我踩过的坑涉及取模操作时如果用int类型保存中间结果可能在加法的过程中溢出所以取模一定要在每一步都做不能只在最后取一次。此外如果要求输出的是方案数量记得初始化dp[0]或者dp[0][0]为1而不是0这个细节有时候能让一道题的得分从0变成全过。2.3 第三题带权网格的最短路变体——我的失分点第三题是我这场考试里失分最多的一道。题面看起来是网格地图每个格子的通行代价不一样有些格子有额外限制需要求从起点到终点的最小总代价。我第一反应是套Dijkstra但因为图比较特殊实际更优的做法是拆点建图或者使用0-1 BFS。这类题目的核心难点在于“额外限制”怎么处理。常见的套路是把一个点拆成多个状态比如拆成二维状态(u, state)再在新图上跑最短路点数和边数都会扩大一个常数倍但思路完全统一。如果限制条件是“某类格子最多经过K次”那就把状态设计成(u, k)表示走到点u且这类格子已经用了k次的最小代价。我当时的问题是我直接按普通BFS写忽略了一些边是有权值的结果样例都过了但提交后有一部分用例超时或者答案错误。复盘之后发现对这类带权网格最优解问题与其在原有图上做文章不如直接使用分层图最短路模板逻辑清晰且不容易漏条件。分层图模板其实不复杂核心代码如下import heapq def solve(grid, start, target): rows, cols len(grid), len(grid[0]) dist [[[float(inf)] * (K 1) for _ in range(cols)] for _ in range(rows)] dist[start[0]][start[1]][0] 0 pq [(0, start[0], start[1], 0)] while pq: d, x, y, used heapq.heappop(pq) if d ! dist[x][y][used]: continue for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)): nx, ny x dx, y dy if not (0 nx rows and 0 ny cols): continue extra 1 if grid[nx][ny] special else 0 if used extra K: continue nd d cost(grid[nx][ny]) if nd dist[nx][ny][used extra]: dist[nx][ny][used extra] nd heapq.heappush(pq, (nd, nx, ny, used extra)) return min(dist[target[0]][target[1]])这种分层图思路在很多笔试里都能用上尤其是“带K次额外操作”的最短路问题。数据范围如果很大还可以优化成0-1 BFS把堆换成双端队列复杂度降一个log但在笔试中Dijkstra足够稳定。2.4 第四题区间查询与贪心优化——高频工程场景第四题考察的是数据结构优化。题目的情景很贴近业务需要对一个数组做若干次区间查询或者从一堆候选值中动态选择最优值。这类题目如果数据范围给到10^5级别暴力一定会超时需要快速联想到O(n log n)级别的解法。我当时采用的是堆加贪心的思路把所有候选值加入一个最大堆或最小堆每次取出最优值并更新再把更新后的值或相关元素放回堆中。这种“堆顶贪心”在笔试里特别常见比如合并区间求最小代价、多路归并找前K小、任务调度求最短完成时间等等。如果要处理区间查询那就不可避免要想到线段树或树状数组。我在实际笔试中强行用了一个相对复杂的线段树但复盘后发现这道题用堆更直观因为查询只是全局性的不涉及范围合并。这也提醒我一件事看到题目先不要急着上高级数据结构考虑一下问题的操作是什么形态——是单点修改、全局查询还是区间修改、区间查询。只有区间相关的操作才需要上线段树全局性的最值问题用堆就好代码量少出bug概率也低。2.5 编程题通用提交技巧读入、输出与自查顺序无论题目难易读入和输出的处理方式会直接影响得分。在线笔试系统一般用标准输入输出输入规模一大Python的input()反复调用就会成为性能瓶颈。我习惯在笔试一开始就写好一个统一的读入模板import sys def main(): data sys.stdin.buffer.read().split() it iter(data) n int(next(it)) arr [int(next(it)) for _ in range(n)] # 业务逻辑 ... if __name__ __main__: main()这样既能避免多次调用input()的开销也能保证读入这一段不用反复调试。输出时要注意不要有额外空格尤其是用print(*list)输出数组时如果list为空要单独处理输出空行。每道题提交之前我给自己定的自查顺序是先跑题目给的样例然后跑一个最小边界用例再跑一个最大范围随机用例如果能构造。如果样例通过但边界用例出错优先检查数组下标、循环边界、数据类型这三个地方占了大多数错误。3. 客观题的覆盖范围与备考点3.1 数据结构与算法高频点客观题里的数据结构部分考得比较多的包括哈希冲突的几种处理方式、二叉树前中后序遍历的变体、排序算法的稳定性和时间复杂度、快排在最坏情况下为什么会退化到O(n²)等等。哈希冲突这部分我建议不要只背定义要理解开放寻址法、链地址法、再哈希法在实际代码里的表现。比如Java的HashMap用的是链地址法当链表长度超过8且数组长度超过64时会转成红黑树这个转换条件就经常被拿出来考。排序算法里堆排序、归并排序、快速排序的时间复杂度都是O(n log n)但稳定性不同堆排序不稳定、快排不稳定、归并稳定。还有一个小细节Arrays.sort()对基础类型数组用的是快速排序对对象数组用的是归并排序目的就是保证稳定性。这种题目不会单独考代码但会在选择题里用很隐蔽的方式问。另外二叉树相关的题目经常和递归、层序遍历挂钩比如判断一棵树是不是完全二叉树、求二叉树的最大宽度、求最近公共祖先。建议把层序遍历的各种变形都练一遍因为它们在实际业务里对应的是“按层级处理数据”的场景。3.2 数据库与存储引擎数据库相关的客观题占了不少比例高频考点集中在索引、事务隔离级别、MVCC、B树这些经典话题上。比如问“联合索引(a,b,c)中哪些查询条件能命中索引”这种题考察的是最左前缀原则。关于索引失效场景有几个容易被忽略的典型情况对索引列使用函数或者计算、隐式类型转换、like通配符放在最前面、使用OR连接非索引列条件。我在复习时把这些场景整理成了一个速查表笔试前翻一遍非常有帮助。事务隔离级别这块需要搞清楚四个级别分别解决什么问题读未提交可能产生脏读读已提交解决脏读但可能产生不可重复读可重复读解决不可重复读串行化解决幻读。MySQL默认用的是可重复读但InnoDB通过间隙锁在一定条件下解决了幻读。这种跨知识的联系经常在选择题里出现只看单个知识点容易懵。MVCC的核心是多版本并发控制通过隐藏字段、undo log和ReadView实现快照读。笔试里常见的问法是判断某个隔离级别下两次查询结果是否相同或者某个事务是否能看到另一个事务的修改。遇到这类题找出事务的创建时间和ReadView生成时机基本就能解。3.3 计算机网络与操作系统网络题比较常规TCP三次握手和四次挥手的细节、TIME_WAIT存在的原因、HTTP和HTTPS的差异、TCP与UDP的区别这些几乎每次笔试都能碰到。我觉得需要特别注意的地方是TIME_WAIT因为它涉及“主动关闭连接的一方为什么要等待2MSL”答案不是背出来的而是要理解它既能让迟到的报文在网络中消失又能保证最终的ACK如果丢失可以重传。操作系统部分进程和线程的区别是必考内容但最近几年倾向于加入协程。协程和线程最大的不同是调度方式线程由内核调度协程由用户态自己调度切换开销小得多。一个形象的类比是线程是公司里不同项目组的人由老板统一调度协程是同一个组里的人自己商量先后顺序不用老板每次都出面。虚拟内存、页面置换算法、缓存一致性这些也会考但难度一般不会特别深。页面置换算法里LRU和FIFO的实现比较常考LRU对应LinkedHashMap的双向链表加哈希表结构这也是Java里的经典实现。3.4 Java、并发与工程实践因为岗位是工程研发客观题里Java内容占比不低。JVM内存分区是必考程序计数器、虚拟机栈、堆、方法区、本地方法栈各自的职责和异常类型要能分清楚。GC方面重点关注垃圾回收算法、可达性分析、G1回收器的特点。一个常考细节是finalize()方法不一定会被调用不能把它当成可靠的资源释放手段这在Java里其实已经基本被废弃。并发编程部分synchronized和ReentrantLock的区别、volatile的可见性和防指令重排、线程池的参数含义和拒绝策略都是高频考点。线程池那里我建议记住一套完整的参数表核心线程数、最大线程数、空闲存活时间、工作队列、线程工厂、拒绝策略。工程实践类的题偶尔会出现比如Git merge和rebase的区别、Linux常用命令的作用、Spring的IOC和AOP思想、依赖注入的好处。这些题不算难但覆盖广如果平时的项目里用了Spring Boot多多少少能答一些。我自己的体会是阿里系的技术栈偏向Java所以Java和Spring相关的知识最好提前过一遍不要只刷算法。4. 考试环境、时间管理与临场心态4.1 笔试前的环境调试在线笔试最容易翻车的不是题目难而是环境出了问题影响心态。我建议不管邮件里怎么提示都先按这个清单检查一遍浏览器优先使用Chrome并更新到最新版本关掉广告拦截插件避免页面元素被拦截。摄像头在系统设置里确认摄像头不被其他应用占用尤其要关掉腾讯会议、钉钉、微信视频等。网络尽量用有线网络如果只能用Wi-Fi提前测速并准备一个手机热点做备用。草稿纸提前准备几张白纸入场检测时根据屏幕提示向摄像头展示正反面。电量笔记本插电手机充满电并开启免打扰。还有一个细节容易被忽略就是浏览器弹窗权限。有些笔试系统在进入考场时要打开新的窗口或者弹窗如果权限被系统拦截页面会一直停留在加载状态。提前在浏览器设置里把考试网站的弹窗权限设为允许能省不少事。4.2 样例过但提交0分的三个原因我这次笔试有一道题出现了样例通过、提交后大面积报错的情况后来复盘发现是典型的三类问题之一第一类是读入格式踩坑。题目说明里写了“多组数据”意味着while循环里要不断处理到EOF但代码里只处理了一次输入或者反过来题目只有一组数据却用了循环导致读入异常。第二类是输出格式不符。常见的是数组之间用逗号分隔但要求是空格分隔或者要求输出一行一个结果却用空格拼接了所有结果。在线评测系统对输出非常严格多一个空格在严格模式下可能判错字符串比较宽松的题目则不一定。保险起见完全按照题目输出的样例格式来。第三类是递归深度过大的问题。在Python里DFS最深一般只到1000层超过之后会报RecursionError。笔试题目如果给到很大数据范围递归写法即使是正确的也会直接崩溃。这种情况要改成循环加栈或者写一个递归入口并手动设置setrecursionlimit(1000000)。碰到这类问题不要反复提交同样的代码那只会浪费时间和提交次数。先打印中间结果把数据范围和输出格式认真读一遍再改代码。4.3 时间分配和取舍策略我这次笔试的时间分配策略是客观题快速做不纠结编程题先按易到难排序第一题和第二题优先保证拿满第三题如果二十分钟没有思路就先跳过第四题用最朴素的方式拿一点超范围用例的分等全部做完再回来优化。实际执行时我第二题花的时间比预期多主要是因为状态定义绕了一下。等到做第三题时只剩不到半小时心态有点急躁结果越急越写不出来。这是一个教训与其在一道难题上死磕二十分钟不如回来检查前面代码的边界把已经“AC”的题稳定住。毕竟笔试看的是总分不是看你做出来的最难题是哪道。5. 考后复盘与秋招准备建议5.1 这次笔试暴露的知识缺口考完当天晚上我做了一件事把四道编程题按“考前准备、考试表现、复盘结论”三个维度各写了几行笔记。这个过程让我明显看到了自己的知识缺口。第一动态规划虽然能写但状态设计不够快。过去刷题时我偏向贪心和双指针因为这类题写起来爽但真实笔试里DP出现的频率非常高这种“回避心理”必须纠正。第二图论的建模能力不足。第三题实际上考察的是分层图我虽然知道Dijkstra但面对“带K次额外限制”这类变体时没有第一时间想到扩展状态维度。这不是算法模板不够而是练题时缺少归类总结。第三数据结构的选型意识不够。第四题明明用堆就可以处理我却一上来就想上线段树导致代码复杂度上升调试时间变长。实际开发中也一样用最简单的工具能解决问题就不要引入重量级框架。5.2 笔试复盘如何反哺后续面试笔试成绩不理想不代表这次笔试没有价值尤其是对于后续的面试环节。很大概率面试官会看到你的笔试表现甚至在面试中追问某道题你是怎么思考的。所以我建议笔试结束后最好趁记忆还在把每道题的思路和代码重新写一遍。我后面在准备其他公司的面试时就把第三题的“分层图最短路”作为重点复习项。面试官如果问“介绍一下你熟悉的最短路算法”可以很自然地把Dijkstra、0-1 BFS、分层图串起来讲阐述它们各自解决什么问题、复杂度如何、适合什么场景这是比背答案更有说服力的准备方式。另外笔试中客观题暴露出的数据库薄弱点也直接影响了我后续面试的准备计划。比如索引部分我只知道概念但不清楚联合索引在排序场景下的优化机制于是用一周时间把所有高频数据库知识点整理成了自己的速查笔记后面的面试中果然被问到类似问题。5.3 给下一届同学的备考建议如果你打算冲击国内大厂工程研发岗我的建议是提前做好三件事第一把算法基础打扎实。不需要追求解出所有Hard题但HOT 100和代码随想录里的经典题要能达到“看到题就能想到解法模板”的程度。尤其是数组、链表、二叉树、哈希表、动态规划、图论和贪心这几大块无论如何不能有短板。第二做套题训练而不仅是单题训练。笔试是限时的单题训练容易让人忽略时间成本。建议每周至少做一次完整模拟按照“10分钟读题25分钟编码5分钟自测”的节奏进行让自己适应“一场考试里多道题切换”的节奏。第三学会总结“题型模型”。不要只刷题不总结看到一个题要先判断它属于哪个模型比如“区间最值”“前K大”“带限制最短路”“状态压缩DP”每个模型记住一个最简解法。这样就算笔试中遇到新题也能快速调用对应方案。结尾这次蚂蚁集团第二场笔试给我最大的触动是秋招笔试不只是在筛选“会不会做题”更是在测试“在压力下如何做决定”。我最后一道题的时间并不充裕与其焦虑还有几道没做不如赶紧回头检查已经提交的代码最终稳住了能拿的分。笔试之后我重新调整了自己的刷题方式把更多精力放在整理题型模型和限时模拟上。秋招还在继续希望这篇复盘能帮到正在准备的同学也欢迎有类似经历的朋友分享自己的处理方式。