尧图精选

阿里云算法岗笔试复盘:KMP、贪心、DP与数据结构考点全解析

🕒 发布时间:2026/9/1 6:48:05 📁 来源:尧图网络
2025年春招我投了阿里云的算法岗3月中旬收到了第一批笔试通知。当天晚上在赛码网线上笔试两个小时题型是单选题多选题3道编程题。整体感觉就是考点覆盖相当广数据结构、排序、贪心、KMP、机器学习基础都碰到了编程题难度梯度明显有一道一眼能看出思路但细节拉满的题还有一道需要绕个弯才能想到状态定义的DP。这篇文章就把这次笔试从投递、准备到实际答题的完整经历拆给你重点分析每道题的思路、考点以及我在现场踩过的坑给后面准备大厂算法岗笔试的朋友一个参考。1. 笔试基本信息与整体感受1.1 投递时间线与笔试通知这里先交代一下背景。我是3月初在阿里云校招官网投递的算法工程师岗位方向偏机器学习平台与AI基础设施base选了杭州。投完简历大概一周左右HR邮箱就收到了笔试邀请邮件里写得很清楚笔试形式在线笔试赛码网平台时长120分钟题型客观题单选多选 编程题3道是否允许本地IDE允许本地写代码但最终需要提交到网页端需要特别提醒一下阿里系大部分岗位用的笔试平台是赛码网不是牛客。这两个平台的编译环境、输入输出处理方式不完全一样赛码网有些题目的输入格式比较刁钻建议提前在赛码网上熟悉一下环境至少做过一两套模拟题不然现场很容易把时间浪费在调试IO上。1.2 题型构成与分值分布先说客观题。这次笔试单选大概10道左右多选5道左右。题目内容比较杂数据结构栈和队列的性质、二叉树遍历、KMP算法next数组求解算法设计排序算法稳定性和时间复杂度、贪心算法适用场景、动态规划的状态转移机器学习基础过拟合的解决手段、交叉验证、常见评价指标精确率、召回率、F1深度学习基础CNN的感受野计算、激活函数的特性概率统计和数学基础贝叶斯公式、期望方差计算这里想强调一下算法岗笔试不只是考算法题机器学习基础和数学基础占比很大。如果你只看《剑指Offer》和LeetCode选择题可能会被拉开差距。编程题是3道我记得大致分布是第一题贪心 排序中等偏易第二题字符串处理 KMP思想或者哈希中等第三题动态规划中等偏难从分值上看编程题是大头每道可能20-25分客观题差不多1-3分一题。所以核心策略还是先把编程题稳住再回头啃客观题。1.3 第一印象题目难度与风格整个笔试做下来的感觉是不考偏题怪题但很考验基础是否扎实。编程题没有特别生僻的算法也没有需要剪枝优化到极致的变态题但每道题都有几个坑边界条件容易漏状态定义如果不仔细想就会绕进死胡同。比如有一道字符串题暴力解法思路很简单但数据范围卡在10^5级别O(n^2)必超时。这就是典型的看起来不难但能不能AC是另一回事的题。如果想要拿高分靠背模板是不够的需要真正理解算法背后的原理能根据题目条件灵活调整。2. 客观题核心考点拆解2.1 数据结构题KMP的next数组一定要会手算这次笔试选择题里有一道非常典型的题对于模式串 p abacaba求其 next 数组。题目是把 next[i] 定义为当前字符之前的子串中最长相等前后缀的长度注意这个定义和部分教材里失配时跳转的位置略有差异做题前一定要先看清定义否则容易错一位。我现场的大致计算过程是这样的模式串a b a c a b anext[0]通常约定为 -1 或 0看题目怎么定义next[1]子串 a最长相等前后缀长度为0next[2]子串 ab前缀a后缀b不相等长度为0next[3]子串 aba前缀a后缀a相等长度1再看ab和ba不等所以next[3]1next[4]子串 abac最长相等前后缀长度0next[5]子串 abaca前后缀a相等长度1next[6]子串 abacab前缀ab后缀ab相等长度2next[7]子串 abacaba前缀aba后缀aba相等长度3所以如果在定义里 next[0]0那么结果就是 [0, 0, 0, 1, 0, 1, 2, 3] 这样的序列。这里想提醒一点很多刷题的人会用KMP模式匹配但要你手工推next数组时反而容易卡壳。笔试前一定要找个下午把所有常见的字符串算法手推一遍包括KMP的next数组、Z算法、Manacher的回文半径这些不要只在IDE里跑过就觉得自己会了。纸上手算和电脑跑代码是两种完全不同的能力。2.2 排序算法稳定性与时间复杂度是高频考点选择题里考了排序算法的稳定性。具体题目不记得了但考点很明确哪些排序算法是稳定的哪些是不稳定的。这里给大家整理一个我常用的记忆方法算法平均时间复杂度最坏时间复杂度是否稳定记忆要点冒泡排序O(n²)O(n²)稳定相邻交换相等不交换插入排序O(n²)O(n²)稳定往前插相等不跨越选择排序O(n²)O(n²)不稳定跨位置交换快速排序O(nlogn)O(n²)不稳定枢轴交换破坏稳定性归并排序O(nlogn)O(nlogn)稳定合并时左优先堆排序O(nlogn)O(nlogn)不稳定堆顶与末尾交换希尔排序约O(n^1.3)O(n²)不稳定分组插入快速排序最坏情况为什么是O(n²)因为如果每次选的枢轴都是最大或最小元素划分极度不均匀递归深度变成n每层还要做n次比较所以是O(n²)。这个点是面试官和笔试都喜欢挖的坑千万别只知道平均复杂度。2.3 贪心算法什么时候能用什么时候不能用选择题里有一道是问以下哪个场景适合用贪心算法。这种题其实是在考察贪心算法的本质贪心是在每一步做出当前看来最优的选择并期望最终结果最优只有具备最优子结构和贪心选择性质的问题才能用。这里有个反直觉的点有些看起来能用贪心的问题其实不能用。比如0-1背包问题就不能用贪心因为物品不可分割局部最优不代表全局最优。而分数背包问题可以用贪心因为可以拿部分物品按单位价值排序从高到低拿就行。笔试时遇到这类题不要凭感觉选。先在草稿纸上构造一个反例如果构造不出反例再考虑选贪心。时间充裕的话用动态规划对比一下会更稳妥。2.4 机器学习基础过拟合与评价指标客观题里考过一个很基础的题如何解决过拟合选项包括正则化、数据增强、Dropout、增加模型参数量。答案是前三个都会减少过拟合最后一个会增加过拟合风险。这类题本身不难但容易在多选上翻车。多选意味着少选、错选、多选都不得分所以每个选项都要单独判断。我的经验是遇到拿不准的选项宁可不选也不要乱选因为错选不仅拿不到分有时还会倒扣看具体规则。另外还考了精确率和召回率Precision 和 Recall的定义。这里有个记忆技巧精确率 预测为正样本且预测正确的数量 / 所有预测为正样本的数量召回率 预测为正样本且预测正确的数量 / 所有真实为正样本的数量可以把精确率理解成我说它是对的里面有多少真的对把召回率理解成所有对的东西里面我找回了多少。如果题目给了一个混淆矩阵要求计算F1就把精确率和召回率算出来再代入F1 2PR / (PR) 就行。3. 编程题第一题贪心 排序思路详解3.1 题目回顾第一题比较友好大致题意是有n个任务每个任务有一个截止时间 d_i 和一个收益 w_i。每个任务需要1个单位时间完成同一时间只能做一个任务。问最大能获得多少收益数据范围n ≤ 10^5d_i ≤ 10^9。这题是经典的任务调度问题贪心策略是按截止时间从小到大排序用小根堆维护已经选择的任务收益。每遇到一个任务先把它加入堆中如果当前选择的个数超过当前任务的截止时间说明有冲突就移除收益最小的那个任务。3.2 为什么这个贪心是对的很多新手学贪心的时候会问我怎么知道这么贪是对的这里我展开讲一下证明思路。我们把任务按截止时间从小到大遍历。假设当前处理到截止时间为 d 的任务那么前面已经处理的任务截止时间都不超过 d这些任务的收益都存在一个堆里。如果堆中任务数量大于 d意味着我们必须在 d 个时间单位内完成超过 d 个任务这显然不可能所以必须放弃某个任务。那么放弃哪一个呢为了最大化收益显然应该放弃收益最小的那个。所以把堆顶元素弹出。这个过程保证了每个截止时间点之前我们都维持了收益最大且不超时的任务集合。这个证明思路叫交换论证法是算法面试里证明贪心正确性的常用方法。核心是假设存在一个最优解我们可以在不影响可行性的前提下把它的结构逐步调整成贪心解的结构并且不降低总收益。3.3 复杂度与细节时间复杂度是O(n log n)因为每个任务最多进堆一次、出堆一次。空间复杂度O(n)。这里有几个细节值得注意如果两个任务截止时间相同排序时第二关键字可以随便排不影响贪心过程收益可能是0或负数吗题目一般给正数但如果出现负数直接不加入堆即可数据范围如果大到10^9不要用数组存每个时间是否占用要用堆的方式否则内存直接爆炸3.4 我现场踩的坑我现场在这道题上耽误了几分钟原因是排序写成了按收益从大到小排序。这就是典型的看起来对但实际是错的思路如果按收益从大到小选任务直观上好像每个任务都能加权处理但遇到截止时间较早的任务时你可能因为先选了高收益的晚截止任务而无法再做早截止的任务反而不如在小根堆里动态调整。正确姿势一定是按截止时间排序 堆维护这个套路在很多题目里都出现过比如求最多能安排多少场会议的变体。建议把这类堆排序的贪心题总结成一个专题一次吃透。4. 编程题第二题字符串与模式匹配4.1 题目回顾第二题是一道字符串题题意大概是给定一个文本串 s 和一个模式串 p求出 p 在 s 中出现的所有起始位置允许字符重叠匹配。s 和 p 的长度都在 10^5 级别且字符串只包含小写字母。看到重叠匹配 10^5 级别第一反应就是KMP算法。KMP 的核心思想是当匹配失败时不要回溯文本串的指针而是利用next数组让模式串跳到合适的位置继续匹配从而把时间复杂度降到O(nm)。4.2 KMP的核心next数组到底怎么用这里我结合选择题里那道next数组计算把KMP的完整流程串一遍。KMP匹配过程大致如下先预处理模式串p的next数组用i遍历文本串s用j表示当前模式串匹配到的位置当s[i]与p[j]不匹配且j0时j next[j-1]或根据定义调整直到匹配或j0如果匹配j如果jm说明找到一个完整匹配记录位置i-m1然后j next[j-1]继续找下一个重叠匹配next数组预处理的本质是模式串的自我匹配。算next[i]时实际上是在对比p[0...i]的最长相等前后缀长度这个过程本身也可以用KMP的思想去优化所以计算next数组的时间复杂度也是O(m)。这里有个常用的模板C风格vectorint buildNext(const string p) { int m p.size(); vectorint next(m, 0); for (int i 1, j 0; i m; i) { while (j 0 p[i] ! p[j]) j next[j - 1]; if (p[i] p[j]) j; next[i] j; } return next; } vectorint kmpSearch(const string s, const string p) { vectorint res; int n s.size(), m p.size(); if (m 0) return res; vectorint next buildNext(p); for (int i 0, j 0; i n; i) { while (j 0 s[i] ! p[j]) j next[j - 1]; if (s[i] p[j]) j; if (j m) { res.push_back(i - m 1); j next[j - 1]; } } return res; }注意这个模板里next数组的定义是最长相等前后缀长度初始next[0]0。如果你习惯使用next数组表示失配时跳转的下标需要把数组整体理解清楚两种定义在写法上会有差异考试时别记混了。4.3 有没有更简单的解法其实这题用哈希也能过。比如滚动哈希Rabin-Karp先算模式串的哈希值然后滑动窗口计算文本串每个长度为m的子串的哈希值如果相等就说明匹配成功。哈希做法的时间复杂度也是O(nm)而且代码比KMP短但要注意哈希冲突。如果你的目标只是AC这道题哈希确实是更快的做法。但如果你后续面试想聊算法深度KMP是更稳妥的谈资。我个人建议是笔试现场求稳用自己最有把握的解法但准备阶段一定要把KMP的原理彻底搞懂因为面试官十有八九会追问为什么KMP是线性的或者next数组的优化版本是什么。4.4 我现场踩的坑这道题我一开始写的是暴力匹配写完发现用例都过了但提交后有一组很大的数据超时了。然后我才想起来数据范围是10^5暴力O(n*m)在最坏情况下会到10^10级别必然超时。所以这里有个经验笔试开始前先浏览一下所有题目的数据范围。看到n≤10^5的题目就要条件反射地思考O(n²)大概率过不了需要O(nlogn)或O(n)的解法。这个扫描数据范围的习惯能帮你省下大量试错时间。5. 编程题第三题动态规划的状态定义5.1 题目回顾第三题是这次笔试里最有区分度的一道题。大致题意如下在一条直线上有n个位置下标从1到n你从位置1出发目标是到达位置n。每个位置 i 有一个能量值 e_i你可以在位置 i 选择消耗不同能量来前进不同的步数。具体来说从位置 i 可以走到 i1 到 ie_i 之间的任意位置。求从1到n的最少步数。乍一看很像跳跃游戏II那题的做法是贪心每次跳得越远越好。但仔细看这里有个区别——题目可能加了一个条件每个位置只能走一次或者有可能跳不到终点这时候贪心就不一定适用了。所以我开始考虑用动态规划做状态定义为dp[i] 表示从位置1到位置 i 的最少步数初始 dp[1]0其余为无穷大转移对于所有能到达 i 的位置 j满足 j e_j i都有 dp[i] min(dp[i], dp[j] 1)这个转移看起来直接但直接做是O(n²)的n10^5时过不了。需要优化。5.2 状态转移怎么优化优化思路是在计算dp[i]时我们只需要找所有满足 j e_j i 的 j 中 dp[j] 的最小值。这类区间内取最小值的问题可以用线段树、树状数组或前缀最小值来优化。但更巧妙的做法是倒过来思考我们把每个位置 j 看成一个区间 [j, je_j]包含端点这个区间表示从 j 出发能直接到达的位置那么 dp[i] 就等于覆盖点 i 的所有区间对应的 dp[j] 1里的最小值对每个 j把 dp[j]1 作为一个候选值应用到区间 [j1, je_j] 上的所有点这样问题就变成了区间更新最小值 单点查询可以用线段树懒标记做。但写线段树的代码量比较大笔试时容易出bug。其实还有一个更简洁的优化注意到dp数组是单调不减的因为走一步至少让位置增加1所以覆盖某个点的区间中起点越靠近当前点、步数越小的 j 优先级越高。我们可以用双指针或者单调队列来维护。但现场我没想完整最后用线段树硬写过了主要测试点。5.3 这题想考察什么能力这道题考察的不仅仅是会不会写DP更重要的是能不能根据题目的约束条件判断必须要优化能不能在多种优化方案中选出代码量小、不易出错的那一种在贪心可能不对的题目背景下敢不敢果断切换到DP说实话这道题如果在LeetCode上刷过类似的区间更新单点查询会很快有思路。所以除了刷题之外做题后的总结归纳特别重要把同一类问题的套路归纳出来笔试时才能举一反三。5.4 我现场踩的坑这题我一开始想用贪心每次跳最远写了一小半发现不行因为题目里有个细节是经过的位置会被消耗掉类似走过的路径上的能量会变化。然后切到DP又因为初始值设置不对导致第一发提交WA。后来把dp数组初始化为一个很大的数比如0x3f3f3f3f才通过。这里提醒一个Dp的常见事故要区分不可达和步数为0。如果初始化全是0那么不可达的位置也会被当成步数0导致后续转移错误。一般建议初始化为INT_MAX/2或者0x3f3f3f3f避免加法溢出。6. 笔试中的实战技巧与平台注意事项6.1 赛码网的使用体验和常见坑赛码网和牛客相比有几个体验差异值得提前注意输入输出模板赛码网的模板有时候不给全需要自己处理多行读取。建议提前记住通用模板比如Python的sys.stdin.read().split()批量读取C的while (cin x)循环读取本地IDE和网页编译环境的差异本地能跑的代码到网页上可能因为编译器版本不同报错建议统一用C11/17标准避免用一些过于新的语法自测用例按钮赛码网有自测功能但样例少不代表AC。我习惯在本地多准备几组边界用例比如空数组、单元素、最大值边界先在本地跑完再粘上去6.2 时间分配策略笔试一共120分钟我个人的分配策略是时间段任务前5分钟快速浏览所有题目标记数据范围和题目难度第5-30分钟做客观题遇到不会的先标记跳过不恋战第30-60分钟编程题第一题 第二题第60-95分钟死磕第三题最后15分钟检查客观题、补齐跳过的题目、检查编程题提交状态这个节奏的核心原则是先把能拿的分都拿到再啃难啃的骨头。很多同学容易在第三题上死磕结果前两题没时间提交非常可惜。6.3 边界条件与特殊用例编程题最容易翻车的就是边界条件。这里分享几个我常用的自测用例模板输入为1个元素时程序不会越界输入为最大值时int不会溢出全部相同元素时算法不会死循环无解时能不能正确输出-1或特殊标记负数、0、极大数等特殊数字6.4 编程语言选择的建议算法岗笔试我比较推荐用C或Python。如果岗位偏工程C更有优势如果岗位偏数据和模型Python更顺手。但要注意C的STL非常方便但要注意unordered_map在一些极端用例下可能被卡哈希笔试平台有些防卡哈希手段比赛时如果不放心可以改用mapPython写起来快但大循环可能超时遇到10^5级别的数据要优先考虑使用内置函数或用numpy思维优化不要裸写Python多层循环Java的话需要自己处理IO记得用BufferedReader而不是Scanner否则大数据输入会慢很多7. 笔试后的复盘与下一步准备7.1 复盘方法错题和超时题笔试结束后我第一时间把3道编程题拿到本地重新做了一遍。复盘的方法是每道题写出两个版本最优解和最容易理解的版本对比现场写的代码找出为什么现场没写对把思路和代码整理成笔记重点记录为什么这个解法是对的和还有没有更好的解法这个习惯坚持下来会发现很多题目之间是有联系的。比如这次的第一题堆贪心和第三题区间更新DP其实都属于决策类问题只是模型不同。做复盘时如果能跨题总结收获会大很多。7.2 笔试后多久会有面试通知阿里云的流程一般是笔试 - 简历评估 - 约面 - 面试技术面HR面。笔试结果不会当场出通常要1-2周如果进入下一轮会有邮件或短信通知。这段时间不要干等可以同步做一些事情复习机器学习/深度学习的理论准备面试中的八股和手撕把简历上的项目细节再过一遍尤其是自己做过的模型、数据、效果指标刷几个高频的算法题保持手感比如TopK、二叉树遍历、股票买卖系列7.3 面试衔接笔试考点很可能变成面试题有一点要特别提醒笔试中出现过但你做错的题面试时很可能换个形式再问你一次。比如这次笔试的KMP next数组推导如果面试聊到字符串匹配面试官可能会让你手写KMP并解释next数组的优化。所以笔试不是考完就完事了错题一定要彻底搞懂不然面试时你会觉得这题我见过但我不会那种感觉比笔试挂掉还难受。我在准备面试时会把笔试的每道题都当成一个面试题种子准备一个深度问答文档比如这道题贪心为什么正确能不能举一个反例如果数据范围扩大怎么继续优化这道题和哪种经典题是同一类这道题和我在项目里的哪些场景相关这样做的好处是面试时遇到相似的题你能很快切换到面试答题模式而不是从零开始想。7.4 笔试后的心态调整最后聊聊心态。大厂笔试刷人率确实不低尤其是第一轮笔试可能有一半以上的人会被筛掉。但这不意味着挂掉笔试就完全没有机会有些部门会根据简历和笔试的综合情况捞人也有补录批次。所以如果这次结果不理想别灰心先复盘自己的问题下一次在别的公司或下一批笔试中发挥出来就好。从我实际经验看春招的笔试一般会有多批次阿里云也不止一次笔试。如果你的时间允许建议多投几个部门批次错开既能积累笔试经验也能增加面试机会。8. 备考资源与长期规划建议8.1 刷题平台选择LeetCode打基础、刷热题100和Hot 100覆盖常见算法和数据结构赛码网熟悉大厂笔试环境尤其是IO格式和IDE体验牛客看面经、刷公司真题很多用户会分享真实笔试题目和解析AtCoder如果想锻炼思维参与AtCoder Beginner Contest是不错的选择题目质量高且偏思维这里要强调的是真正到了笔试现场最实用的不是这题我在LeetCode刷到过原题而是这题我能快速识别出类型并且调用出一套成熟解法。所以刷题的意义在于建立场景-算法-复杂度的映射关系而不只是记忆代码。8.2 机器学习/深度学习的复习重点算法岗笔试里机器学习理论经常占不少分值。推荐按下面这个清单复习模型评估精确率、召回率、F1、ROC-AUC、PR曲线交叉验证K折、留一法、分层抽样正则化L1、L2、Dropout、Early Stopping优化算法SGD、Momentum、Adam、学习率衰减损失函数交叉熵、均方误差、Hinge Loss经典模型逻辑回归、SVM、决策树、随机森林、GBDT深度学习CNN、RNN/LSTM、Transformer基础、感受野和参数量计算这些内容不一定要刷题但基本的公式推导和概念要清楚。笔试的选择题考得不会很深但如果你连精确率和召回率的区别都说不清那就很被动了。8.3 关于算法岗与AI Infra方向的一点思考我投的方向偏机器学习平台与AI基础设施这类岗位对算法基础的要求不会降低但同时会额外关注系统工程能力比如分布式训练、模型部署、性能优化等。如果你也是投类似方向建议在准备笔试的同时多了解一些行业常见的开源工具和架构比如模型训练框架、推理加速手段、GPU集群调度等这些在后续面试中会是加分项。不过笔试阶段还是以算法题和机器学习基础为主系统工程的知识更多是面试阶段发挥。8.4 时间规划建议如果从现在开始准备算法岗笔试我建议按3-4周来规划第一周数据结构基础数组、链表、栈、队列、树、图 高频算法排序、二分、双指针第二周动态规划专题 贪心专题 字符串专题KMP、哈希第三周机器学习基础 数学基础 刷公司真题第四周模拟笔试 查漏补缺重点整理错题不要把战线拉得太长笔试需要的是熟练度和手感集中一个月高强度准备比拖三个月断断续续的效果好得多。9. 写在最后的一点个人体会这次阿里云算法岗笔试给我的最大感受是大厂算法笔试已经从考你会不会某个算法变成了考你能不能把多个知识点串起来解决实际问题。它不会直白地让你实现一个快速排序而是给你一个看起来很像业务场景的题让你自己决定用什么数据结构、什么算法、如何优化。另外笔试的临场状态也很重要。我这次中间有一道题卡了快二十分钟当时心里有点慌但后来深呼吸了一下果断跳过写下一题再回过头来慢慢想反而思路更清晰了。笔试不是比赛拿奖是尽力拿分所以学会战略性放弃很关键。最后再分享一个小技巧笔试前把浏览器书签里提前存好常用代码模板。我知道有些平台不允许复制自己本地的代码但提前把模板默写在脑海里是没问题的。比如快速幂、并查集、线段树建树、KMP匹配、二叉树迭代遍历、拓扑排序这些高频模板考前默写一遍考场上能省下大量时间。希望这篇复盘对正在准备大厂算法岗笔试的你有点帮助。如果还有关于笔试、面试准备的问题欢迎在评论区交流。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →