
1. 笔试全景先把这仗的“战场地图”看清楚先说结论2023年蚂蚁春招技术通用岗笔试整体风格和我之前参加过的其他互联网大厂笔试不太一样它更偏“算法基础 计算机基础 工程直觉”的组合不是单纯刷题就能糊弄过去的但也不是那种劝退级的竞赛难度。如果你正在准备类似的春招笔试这篇内容应该能帮你少走不少弯路。蚂蚁的技术岗位笔试通常安排在春招启动后的1-2周内具体时间以邮件通知为准。我当时收到通知后大概有5-7天的准备窗口时间说紧不紧、说松不松关键看你怎么利用。笔试形式是线上做题全程摄像头监控屏幕录制这个不用太紧张正常作答就行。先说题型分布。2023年蚂蚁春招技术通用岗笔试分为两个大部分第一部分是计算机基础选择题范围覆盖数据结构、操作系统、计算机网络、数据库、Java或C语言特性以及少量逻辑推理题总共大概40-50道第二部分是编程题一般是3道难度呈阶梯式上升从“基础数据结构操作”到“中等难度算法”再到“偏竞赛思维的优化题”。时间上选择题部分限时60-80分钟编程题部分限时90-120分钟整体加起来的压力还是有的。特别是编程题如果你在选择题上磨蹭太久后面写代码的时间会被严重压缩这是很多人翻车的主要原因。关于难度判断我的体感是选择题整体难度中等偏上会比学校期末考试难一点比考研408真题略简单一些但胜在范围广、问法灵活有些题你看上去是考A实际拐了个弯在考B。编程题第一题基本是送分题二叉树遍历、链表操作、字符串处理这个级别第二题是常规的中等难度比如动态规划的基础模型、图的最短路径、区间合并之类的第三题就有点看运气了有时候是思维题有时候是复杂DP或贪心加数据结构的组合优化做不出来很正常拉开差距的关键在前两题能否全对、第三题能否拿部分分。我见过不少同学备考时只刷编程题对选择题不管不顾结果编程题做得还不错选择题错得一塌糊涂。这里要提醒一句蚂蚁笔试的成绩是综合评定的选择题比重不低而且选择题做错倒扣分部分年份有这个规则裸考选择题等于送人头。后面我会详细拆每个知识点的准备方法。2. 核心考点拆解面试官到底在考你什么2.1 数据结构与算法不只是“会做”而是“为什么这么做”数据结构这块是重中之重笔试选择题几乎必考以下几个方向数组和链表的区别与适用场景、栈和队列的应用、二叉树的各种遍历方式及变体、堆的插入删除复杂度、哈希表的冲突解决策略、图的存储方式邻接矩阵vs邻接表和遍历算法、排序算法的稳定性和复杂度对比。我的经验是蚂蚁的题目喜欢“换皮”表面看是问你ArrayList和LinkedList的区别实际是在考你底层内存布局对随机访问和插入删除性能的影响这时候你不仅要说出“ArrayList底层是数组LinkedList底层是双向链表”还要能解释为什么ArrayList的插入在中间位置是O(n)而LinkedList是O(1)但实际遍历成本高以及CPU缓存友好性对实际性能的影响。举个具体例子我在笔试里遇到一道题给定一个链表判断是否有环并要求说明为什么快慢指针法的空间复杂度是O(1)。这种题很多同学都会做代码也能写出来但要是问你“为什么快指针速度是慢指针的两倍相遇一定能发生”有些人就卡住了。这里的关键是如果有环快慢指针进入环后快指针每次比慢指针多走一步相当于在环上追赶慢指针环的长度是有限的所以追及一定能完成这就证明了算法的正确性。编程题方面高频题型包括二叉树相关的递归与迭代、动态规划背包问题、最长递增子序列、编辑距离、图的BFS/DFS尤其是有状态约束的搜索、前缀和与差分、二分答案、并查集、单调栈。建议你在准备时按题型建立自己的“解题模板”比如动态规划的五步法确定dp数组含义、确定递推公式、初始化、确定遍历顺序、举例推导、BFS的状态压缩处理、并查集的路径压缩和按秩合并这些模板不是让你死记硬背代码而是帮你快速识别题目类型、少走弯路。排序算法这块别只背复杂度表要理解稳定性是什么概念、什么场景下需要稳定排序。比如排序后要保持相同元素的原始相对顺序那么稳定排序和不稳定排序的结果差异就体现出来了。常见排序里冒泡、插入、归并是稳定的快排、堆排、选择是不稳定的这个选择题考点几乎年年出现。2.2 操作系统与计算机网络八股文的“活学活用”操作系统的考点集中在进程与线程、进程调度算法、死锁的四大条件和预防方法、内存管理分页分段、虚拟内存、页面置换算法、文件系统的基本概念。蚂蚁的题不会直接问你“死锁的四个必要条件是什么”而是给你一个场景比如两个线程分别持有锁A和锁B然后互相等待对方释放锁问你属于哪种情况、如何避免。这里我给你一个非常实用的应试思路把操作系统涉及的各种机制和算法想成是“解决某个问题的方案”比如虚拟内存解决的物理内存不够用的问题、页面置换算法解决的是缺页率过高的问题、多级反馈队列解决的是兼顾响应时间和吞吐量的问题。这个思路能帮你应对很多场景化选择题。计算机网络的重点是TCP/IP协议栈。TCP三次握手和四次挥手的状态迁移图必须烂熟于心尤其是TIME_WAIT状态存在的原因——主动关闭方要确保最后一个ACK能被对方收到如果丢了可以重发同时让本连接产生的报文在网络中消逝避免干扰后续连接这个知识点我印象里基本每场笔试都会遇到。TCP和UDP的区别也是必考传输控制、面向连接vs无连接、可靠vs尽力而为了、首部开销不一样如果你做过网络编程理解起来很容易。关于HTTP和HTTPS要掌握HTTP请求方法GET、POST、PUT、DELETE等的语义差异、状态码的含义尤其301、302、400、404、500、502、504、Cookie和Session的区别与联系。HTTPS的握手过程也是高频考点非对称加密交换密钥、对称加密传输数据、CA证书验证身份这个流程要能说出来。我在笔试中做到一题客户端访问一个HTTPS网站浏览器提示证书不受信任可能的原因有哪些。选项里包含证书过期、证书签发机构不被信任、域名与证书不匹配、服务器时间不正确。如果只背HTTPS握手流程而不理解证书验证的细节这题容易选漏。补充一点服务器时间不正确确实会导致证书有效期判断出错这个选项很多人会漏选。2.3 数据库与语言基础看起来简单坑最密集数据库的考点主要围绕SQL语句、索引、事务四大特性ACID、隔离级别与并发问题、范式理论。蚂蚁的SQL题不会太复杂但会考你一些容易忽略的细节比如GROUP BY与聚合函数配合时WHERE和HAVING的执行顺序差异、多表连接时ON条件和WHERE条件的过滤时机不同内连接时这两个等价外连接时ON决定匹配条件、WHERE决定最终返回行。索引这块是重点。聚簇索引和非聚簇索引的区别、联合索引的最左前缀原则、覆盖索引优化查询、索引失效的场景对索引列使用函数、隐式类型转换、LIKE以通配符开头、OR连接非索引列等。务必理解为什么这些场景会导致索引失效而不是死记结论因为笔试题很可能给你一个具体SQL让你判断是否走索引。Java和C二选一的话我被问到的是Java方向。Java考察点包括面向对象三大特性封装、继承、多态的理解、String/StringBuilder/StringBuffer的区别、HashMap的底层实现原理JDK 1.8后引入红黑树解决哈希冲突过长问题、并发编程synchronized和ReentrantLock的区别、volatile的可见性和禁止指令重排、线程池参数含义、JVM内存区域划分和垃圾回收的基本思想。如果你选C重点看RAII、智能指针、虚函数、多态的实现原理、STL各容器的底层数据结构和使用场景。语言基础这块没有太多捷径但可以通过高频题清单来查漏补缺我会在下一节给一个更具体的内容清单。数据库还有一个常见的坑事务隔离级别。4个级别读未提交、读已提交、可重复读、串行化对应的并发问题脏读、不可重复读、幻读要能一一对应。MySQL默认是可重复读但通过MVCC机制解决了大部分幻读问题这个深入理解会帮你答对相对较难的题。2.4 逻辑推理题别小看这部分“分量”逻辑推理题大概有5-8道很多人不重视觉得分值占比不高但蚂蚁的逻辑题其实出得挺讲究不是那种脑筋急转弯而是考你归纳总结能力和条件推理能力。常见题型包括数字规律、图形推理、条件排除、真假话判断、最优策略选择。我自己的解题经验是遇到数字规律不要急着想复杂公式先看差值、差值差值、相邻项比值、奇偶项拆分绝大多数题目逃不出这几种套路遇到条件排除就用列表法或矩阵法把每个条件逐一标注在对应位置排除矛盾项遇到真假话判断一定用假设法假设某个人说的是真话看是否产生矛盾能推就推不能推就换一个假设。关于逻辑题的复习不需要专门刷大量题保持手感就行。每两天做10道公务员行测的判断推理题基本就能覆盖各种题型了。难度的上限不会超过行测所以不用焦虑。3. 编程题实操从读题到AC的全流程拆解3.1 编程环境与准备工作蚂蚁编程题支持的语言比较多Java、C、Python、Go都行但建议你优先用自己最熟练的语言不要在这时候尝试新语言。我个人推荐Java或C因为这两类语言在写算法题时性能稳定、API丰富而且如果你投的是技术通用岗面试时大概率也会以你笔试用的语言为主来追问。笔试系统一般是牛客网或赛码网建议提前去这两个平台熟悉一下在线编程的操作方式尤其是输入输出处理。牛客网的输入输出题上有很多坑比如数据是一行读入还是多行读入、有没有数字之间的空格、字符串里面有没有空格、是否需要循环读取到EOF这些细节如果没提前踩过考试时会浪费大量时间在调试输入输出上。我这里给你一个Java的快速输入输出模板在笔试中实测非常好用尤其是在数据量大的时候import java.io.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw new BufferedWriter(new OutputStreamWriter(System.out)); String line; while ((line br.readLine()) ! null) { String[] parts line.split( ); int n Integer.parseInt(parts[0]); int m Integer.parseInt(parts[1]); // 处理业务逻辑 bw.write(String.valueOf(result)); bw.newLine(); bw.flush(); } br.close(); bw.close(); } }使用BufferedReader和BufferedWriter而不是Scanner是因为Scanner在读取大量数据时性能较差可能会在数据规模大的用例上超时。这不是玄学我实测过同一个题如果数据量是百万级别两种方式的时间相差3-4倍。3.2 典型例题实战字符串解码问题2023年蚂蚁笔试的编程题第一题我记得有一道是字符串解码类似LeetCode 394不保证每个场次都一样但这题型的代表性和频率很高。我拿这个题来演示一遍我的完整做题流程。题目描述大概是给定一个经过编码的字符串返回它解码后的字符串。编码规则是k[encoded_string]表示方括号内部的字符串重复k次。例如3[a2[c]]解码为accaccacc。拿到这道题我的第一反应是“这题考栈或递归”。看到嵌套结构马上要想到这两条路不需要犹豫。画一下结构3[a2[c]]展开的时候最内层是a2[c]如果我能先处理内层再处理外层这就是天然的递归结构而用栈来模拟这个过程本质上就是在做显式的递归。用栈的解法遍历字符串遇到数字就统计完整数字注意可能多位数遇到字母就收集连续字母遇到[就把当前累积的数字和字符串分别入栈并重置遇到]就出栈将当前字符串重复对应次数拼接到栈顶字符串后面。public static String decodeString(String s) { DequeInteger countStack new ArrayDeque(); DequeStringBuilder strStack new ArrayDeque(); StringBuilder cur new StringBuilder(); int num 0; for (char c : s.toCharArray()) { if (Character.isDigit(c)) { num num * 10 (c - 0); } else if (c [) { countStack.push(num); strStack.push(cur); cur new StringBuilder(); num 0; } else if (c ]) { int repeat countStack.pop(); StringBuilder prev strStack.pop(); for (int i 0; i repeat; i) { prev.append(cur); } cur prev; } else { cur.append(c); } } return cur.toString(); }这里有两个值得说的小细节。第一个细节是数字的累加num num * 10 (c - 0)很多同学写的时候直接num c - 0遇到12[a]就崩了。笔试的时候要实际跑测试用例不能光靠脑补。第二个细节是使用ArrayDeque而不是Stack因为Java官方推荐使用Deque接口Stack类继承自Vector线程安全但性能有锁开销在算法场景下没必要。3.3 典型例题实战动态规划求最长递增子序列第二题我印象比较深的是LIS最长递增子序列它不一定完全一样但DP模型的核心思路是通用的。题目大意给定一个无序整数数组找到其中最长递增子序列的长度。经典解法有两种一种是O(n^2)的动态规划一种是O(n log n)的贪心二分维护一个tails数组tails[i]表示长度为i1的递增子序列的末尾元素最小值迭代更新。笔试中如果时间充足建议直接写O(n^2)版本代码简单不容易出错如果题目明确要求O(n log n)或者n很大比如10^5级别那就必须用二分优化。我建议你把两种解法都掌握特别是二分解法的边界条件代码里最容易出错的地方是二分查找时left和right的初始值以及循环终止条件。public static int lengthOfLIS(int[] nums) { int[] tails new int[nums.length]; int len 0; for (int num : nums) { int left 0, right len; while (left right) { int mid left (right - left) / 2; if (tails[mid] num) { left mid 1; } else { right mid; } } tails[left] num; if (left len) len; } return len; }这里tails数组并不是真正的LIS序列它只维护“末尾元素最小值”这个信息。比如数组[1, 5, 2, 3]处理完前三个元素时tails是[1, 2]它并不是实际的递增子序列[1, 5]但对于计算长度来说已经足够了。理解这一点很重要因为面试官可能会追问你的tails数组是不是最终最长递增子序列答案是否定的。这也是一个常见的讨论点。3.4 典型例题实战需要灵活绕弯的优化题第三题通常不好归纳成单一模型但有一类我印象比较深在一个较大范围内求满足某种条件的最值两个关键维度互相制约要求处理一组查询或批量计算。遇到这类题我提供的策略是不追求AC先确保你能写出暴力解法拿到部分分。笔试系统一般是按通过的测试用例比例给分的你暴力解能过30%-60%的用例已经是不错的结果。而且很多第三题的暴力解法代码量不大30分钟完全能写出来。剩下时间再思考优化。举个例子如果题目是“给定一个数组和若干查询每个查询给一个区间[l, r]求区间内出现次数最多的数”暴力的做法是对每个查询遍历区间时间复杂度O(n*m)数据量大时超时但能拿部分分。优化思路可能是莫队算法或离线处理树状数组这里就要看你的算法功底了。考场上最忌讳的事一看到第三题觉得难就开始各种复杂的优化尝试最后优化没写出来暴力解也没交上去。我的建议是先把暴力解写完并提交保证这部分分拿到手然后再去优化。这一条经验很重要它能直接决定你是否能从这场笔试中晋级。4. 常见问题与避坑指南这些都是前人用血泪换来的4.1 时间分配别让选择题拖垮编程题我见过太多人选择题做得很认真每道题都反复斟酌结果编程题只剩40分钟。记住一个硬性建议选择题会就选超过90秒没有思路就标记下来跳过最后有时间再回头想。选择题的分值通常是1-2分一道你在一道题上纠结5分钟就算做对了也可能丢了后面一道编程题的分性价比完全不划算。编程题的时间分配建议是第一题20分钟内完成并确保正确第二题30-40分钟留40分钟左右给第三题。如果第一题写完后还有时间建议你先去检查一遍边界输入比如空数组、单个元素、极大极小值、负数这些边界条件是笔试隐藏用例的重灾区。4.2 选择题的常错点整理我在备考时总结了一些选择题的常错点这里列一个速查表你看看自己是不是也踩过这些坑考察方向常错点正确理解HashMap认为HashMap线程安全HashMap非线程安全并发场景用ConcurrentHashMapTCPTIME_WAIT出现在主动关闭方四次挥手中先发起FIN的一方进入TIME_WAIT数据库认为可重复读解决了幻读MySQL InnoDB可重复读通过MVCC间隙锁解决幻读但标准SQL中未解决排序快速排序平均与最坏复杂度混淆平均O(n log n)最坏O(n^2)发生在每次划分极度不平衡时操作系统分页和分段的区别分页是物理划分无逻辑意义分段是逻辑划分段内连续、段间不连续JVM认为所有对象都分配在堆上通过逃逸分析部分对象可在栈上分配JIT优化还有一个容易被忽略的点Java中Integer的缓存机制。Integer a 127; Integer b 127; a b返回true但Integer a 128; Integer b 128; a b返回false因为Integer默认缓存了-128到127的值。这种题形似“考察相等比较”实际上考的是语言底层机制基础不牢固的话很容易掉坑。4.3 编程题的超时与越界两个最让人跪的问题编程题提交后报“运行超时”或“答案错误”是很常见的但很多时候不是你算法的思路错了而是一些细节没处理好。超时问题尤其是Java选手最容易被输入输出写法坑。前面提到了做算法竞赛级别的输入时用Scanner和System.out.println大概率超时换BufferedReader和BufferedWriter基本就能解决。另外如果同一个输出结果被多次打印考虑用StringBuilder先拼好再一次性输出比如你要输出一个数组的所有元素别每个元素调用一次System.out.print。整型越界是另一个高频坑。int最大是2^31-1约21亿很多题目给的数值范围看似不会超但中间乘法过程会超。比如计算n的阶乘、计算两个大数相乘再取模中间结果很容易溢出。安全做法是涉及可能超int范围的运算直接使用long如果题目数据范围超过long要用BigInteger并考场上尽量选择其他解法避免这种问题。还有个细节是负数取模在Java中的结果和你预期的可能不一样-1 % 10在Java中是-1而不是9这在某些哈希类题中会直接影响结果需要手动加模数调整到正数。4.4 心态与应试笔试也是信息战关于笔试前后的整体策略有几点想特别分享。笔试开始前准备好身份证和草稿纸。虽然线上笔试在电脑上操作但草稿纸非常有用尤其是逻辑推理题和动态规划的推导题在纸上画状态转移表比盯着屏幕干想高效得多。很多同学觉得笔试不涉及手写就不准备草稿纸这其实是错的。笔试过程中切屏和代码粘贴提醒要小心。部分在线笔试系统会检测切屏行为你不小心切到浏览器查资料可能导致该场次成绩作废。建议在笔试前把所有需要用到的工具比如本地IDE提前打开把系统允许的编程语言环境配置好防止中途切换窗口。编程题的提交策略不要求一次性AC但每道题至少要提交一次确保有分。如果代码在本地IDE运行正确但在线提交报错优先检查类名是否写成了Main、有没有包名、输入输出格式是否完全匹配。这些细节在牛客网的模拟练习里反复出现提前练一遍能避免大量低级错误。笔试结束后的半小时内趁记忆还新鲜把你没做出来的题和不确定的选择题记录下来然后去查漏补缺。这是因为蚂蚁的笔试通过后面试官会拿到你的笔试报告在面试环节可能会追问笔试中某个题的优化思路。如果你当时做不出来但面试前搞明白了照样能加分。我身边就有人面试时被问“你笔试第二题用的O(n^2)解法有没有想过更优解”他提前复盘过顺利答上来了最终通过了面试。5. 准备时间线与复习资源7天冲刺具体怎么做如果你离笔试时间还有一周左右可以参考我这份7天冲刺计划按天来安排任务每一步都具体可做。第1天摸底与查漏。拿出一套往年的模拟卷或真题不限时完整做一遍标记出自己哪些知识点不会、哪些题型不熟。这样做比漫无目的地刷题高效得多它能帮你把有限的复习时间花在最薄弱的地方。第2-3天集中过核心选择题知识。数据结构重点看二叉树和哈希表相关题操作系统重点看进程调度和死锁相关题计算机网络重点看TCP和HTTP相关题数据库重点看索引和事务隔离级别相关题Java重点看集合和并发相关题。每天安排两个方向每个方向刷30道以上选择题错题标记并看解析不要只求数量。第4-5天算法编程题专项。每天早上花1小时刷2-3道高频题二叉树、DP、BFS/DFS、并查集、前缀和下午挑1道有难度的题做深入分析。务必在你的本地IDE里写不要只看题解写和看完全是两回事。提交到LeetCode或牛客并保证AC。第6天模拟实战。找一段完整的时间比如上午10点到12点用牛客网的模拟环境做一套完整的模拟笔试。严格按考试时间、考试规则来包括摄像头监控的感觉也尽量模拟这样你才会对“有限时间内的紧张感”有切身体会。第7天错题复盘 放轻松。把前6天做错的题重新过一遍尤其是选择题的错题重在理解为什么错而不是记答案。编程题可以浏览一下每道题的核心思路不用完整写一遍。晚上早点休息考试当天心态比临时抱佛脚更重要。复习资料方面我不推荐买一堆厚厚的笔试合集书性价比太低。比较实用的资源包括LeetCode热题100这100道覆盖了绝大多数笔试编程题的考点、牛客网的历年真题区输入输出坑最多的地方、以及你目标岗位方向的面经汇总帖子经常有人回忆考了哪些知识点直接锁定搜索范围。操作系统、计算机网络、数据库的教材不用全看挑重点章节看就行。我个人认为笔试准备的核心不是“题海战术”而是“高频考点覆盖 核心算法熟练 临场心态稳定”三者的平衡。你不需要在笔试中考满分只需要在整体人群中排到前20%-30%就能拿到面试资格所以有些难题战略性放弃完全是可以接受的。关键是该拿的分稳稳拿到该写的题稳稳AC心态不崩结果就不会太差。