ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

2024小米算法岗笔试复盘:高频考点与编程题实战解析

2026/9/1 4:36:55 拓冰建站 浏览量
2024小米算法岗笔试复盘:高频考点与编程题实战解析 每年秋招算法岗笔试都是筛人最狠的一关。今年小米集团的算法岗我报的是第二批笔试整个过程从报名到考试间隔不到一周准备时间其实很紧。考完我把题目和整个答题过程复盘了一遍今天这篇就把第二批算法岗笔试的题型结构、高频考点、编程题解法以及踩坑细节全部分享出来。如果你也打算冲小米或者其他互联网大厂的算法岗这篇复盘应该能帮你建立一个相对完整的备考坐标系。先说结论小米算法岗笔试不是那种“偏题怪题满天飞”的风格整体上非常重视基础数据结构、经典算法、机器学习理论都会覆盖编程题考的是能不能在有限时间内写出可运行的干净代码。和第一批相比第二批的题型和难度没有本质差异但部分选择题的细节抠得更深编程题的数据范围更大明显是在逼你考虑时间复杂度。整个过程下来我的感受是把基础打扎实比刷一堆偏题有效得多。1. 2024秋招小米算法岗笔试整体印象与考情分析1.1 笔试形式、平台与时间安排今年小米的笔试统一走在线笔试平台算法岗第二批仍然是双机位监控正面电脑摄像头要拍到脸手机开二机位放在侧后方考试过程中不能切屏切屏次数多了会被系统记录严重的直接判作弊。这一点要特别提醒一下考试前至少留半小时调试设备浏览器建议用Chrome或Edge的较新版本很多在线笔试平台对旧版浏览器兼容性很差万一中间崩了非常影响心态。时间安排是固定时长从开考开始倒计时到点自动交卷。我参加的那场总时长大概是两个小时左右题量并不算大但因为包含编程题时间其实一点都不宽裕。题目在开考时统一放出可以自己选择先做哪部分不过大部分人的习惯是先把选择题快速扫一遍再集中精力搞编程题最后留时间写简答和场景题。笔试平台本身支持本地IDE编译也支持在网页里直接写。建议提前准备好输入输出模板尤其是用C或者Java的同学把ios::sync_with_stdio(false)、Scanner这些常用模板背熟能省下不少时间。Python的同学则要注意sys.stdin.read()这类批量读入方式避免在大数据量输入下卡在读入环节。1.2 第二批与第一批的差异从第一批放出来的面经和讨论看小米算法岗几批笔试的题型框架是一致的都是“选择题 编程题 简答/场景题”的组合但第二批有几个明显的调整选择题中机器学习理论的比例更高尤其是正则化、损失函数、模型评估这几个方向。编程题的测试数据范围更大部分题目需要用到long long直接用int很容易溢出。场景题不再是简单的“介绍一下你熟悉的模型”而是给了具体业务限制比如数据量、延迟要求、冷启动问题让你给完整方案。这意味着第二批更看重候选人的工程落地意识而不是单纯刷题家。用一句通俗的话说第一批问的是“你会不会”第二批问的是“你敢不敢真上项目”。1.3 题型分布与分值权重参考下面这张表是我根据自己的答题经历和网上讨论整理出来的具体批次可能有出入但总体框架是可以参考的题型题量大致分值建议用时单选/多选题15题左右30分25~30分钟编程题2题50分70~80分钟简答/场景设计题1题20分15~20分钟选择题是单选多选混着出多选少选错选都不得分这个在做题时一定要看清题干要求。编程题是ACM模式也就是需要自己处理输入输出不是力扣那种只写核心函数的形式。简答/场景题是文字作答没有标准答案但很看答题结构和细节。从分值占比就能看出来编程题是笔试的绝对核心两题就占了50分。选择题虽然分值不高但它决定了你能不能拿到一个基础分错太多的话即使编程题AC了也很难进面试。2. 高频考点盘点数据结构、经典算法与模型原理2.1 数据结构基本功KMP、堆、并查集这些“老熟人”小米笔试的选择题里数据结构考察得非常细致而且特别喜欢在经典算法上做变形。举个例子模式串匹配的KMP算法很多人刷题时会直接跳过觉得自己“会用库函数就行”但笔试它就敢直接考next数组的手算推导。我印象里有一道题给了一个模式串要求写出某个位置失败后模式串应该移动到哪里本质上就是考KMP的next数组计算。这里说一个KMP的快速手算方法。next数组有很多种定义版本小米题目里如果没特别说明一般用的是“对于模式串的第i个位置next[i]表示该位置之前的子串中最长相等前后缀的长度”。例如模式串p abacaba我们手算时逐个前缀分析前缀最长相等前后缀next值a无0ab无0abaa1abac无0abacaa1abacabab2abacabaaba3平时可以多练几个字符串手算next数组考场上别指望编译器帮你算选择题必须一眼能看出来。除了KMP高频数据结构还包括栈和队列的单调性应用单调栈、单调队列、堆的建堆与堆排序复杂度、并查集的路径压缩与按秩合并、哈希表的冲突处理方式、LRU缓存的实现思路。其中LRU在简答题里出现过好几次建议把“哈希表 双向链表”的实现方案背熟能讲清楚get和put的时间复杂度为什么是O(1)。2.2 经典算法快速幂、DP、贪心、Dijkstra与拓扑排序经典算法方面本次笔试的重头戏是动态规划、贪心和图论算法选择题和编程题都会涉及。快速幂是小米笔试常考的基础算法看起来简单但很多人写起来会忽略指数为0、底数取模这些边界。模板我就不贴了提两个要点一是二进制拆分的思路把指数按二进制位分解底数不断自乘二是乘法结果要随时取模防止溢出。这类题一旦考到基本都是给分题丢分很可惜。动态规划考的范围很广从经典的背包问题、最长递增子序列、编辑距离到网格路径类问题都有可能出现。笔试里的DP题通常不会直接告诉你“这是DP”而是给一个看似是搜索或贪心的题目让你自己发现最优子结构。所以做题时第一反应不要急着写暴力搜索先看数据范围如果n在1000以上大概率是O(n^2)的DP如果n在10^5级别那就要考虑O(n log n)的优化比如LIS的二分优化、状态压缩、单调队列优化等。贪心算法在选择题里经常以“下列说法正确的是”的形式出现考察你是否知道某个经典贪心问题的反例。比如“每次选收益最大的任务”不一定能获得最大总收益这类题目需要你对贪心策略的正确性有判断能力不能凭感觉选。图论方面Dijkstra算法的变体、拓扑排序判断有向图是否有环、并查集判连通分量都是高频考点。Dijkstra注意堆优化版本的复杂度是O((VE)logV)选择题会反复考二分图匹配如果出现大概率是考最大匹配等于最小点覆盖的结论不一定会让你手写匈牙利算法。2.3 机器学习与深度学习基础从XGBoost到损失函数算法岗笔试和纯开发岗笔试的最大区别就是必然有一批选择题考机器学习理论基础。今年第二批在这方面出得很细印象比较深的有这么几类第一类是模型对比题比如“XGBoost相比GBDT做了哪些改进”。这种题不能只背结论得能从原理上说清楚XGBoost在目标函数里加了二阶泰勒展开支持自定义损失函数加入了正则项控制模型复杂度特征粒度上支持并行分裂点的选择可以近似直方图算法加速还能处理缺失值。如果只是背“XGBoost比GBDT快、效果好”这种话很容易在多选里漏选。第二类是损失函数和正则化的细节。比如交叉熵损失对Softmax输出的梯度形式L1和L2正则化的区别为什么L1能产生稀疏解Dropout在训练和推理时的行为差异。这些概念看起来基础但出题人非常擅长在选项里混入“看起来对”的错误表述比如“Dropout推理时也要随机失活”这种明显错误的选项其实就是送分点。第三类是模型评估指标。准确率、精确率、召回率、F1、AUC、ROC曲线是必考项但这次还考了类别不平衡场景下应该优先看哪个指标以及如何在数据层面做采样。这提醒我们复习时要关注“指标在什么场景下失效”而不仅仅是背公式。深度学习部分卷积神经网络和Transformer是重点。选择题会考CNN感受野的计算、BN层在训练和推理时的区别、注意力机制的公式Q、K、V怎么算以及Transformer里的位置编码为什么重要。建议把这些模型的经典结构图自己画一遍输入输出维度手推一遍对做选择题非常有帮助。2.4 优化与控制类算法粒子群、模拟退火、卡尔曼滤波这些“边角料”小米笔试还有一个特点就是偶尔会冒出一两个看起来超出常规算法体系的概念题比如粒子群算法、模拟退火、卡尔曼滤波、PID控制。这些在AI算法岗的日常工作中不一定用得上但出题人可能觉得“搞算法的应该有所耳闻”。我的建议是不需要深入源码级掌握但要能说出核心思想。粒子群算法的核心是“群体协作 个体历史最优 群体全局最优”模拟退火的核心是“以一定概率接受更差解从而跳出局部最优”卡尔曼滤波的核心是“预测 更新融合先验和观测”PID控制的核心是“比例、积分、微分三项组合调节”。这类题在笔试里属于“知识面题”会就是会不会也能靠常识排除部分选项花太多时间深挖不值得。音频重采样、图像锐化的拉普拉斯算子、Sobel边缘检测这类题目可以归为“数字信号处理/图像处理常识”。如果投的不是CV或音频算法岗这类题占比很低但至少要知道拉普拉斯算子是二阶微分算子Sobel是一阶微分算子都属于卷积核操作。3. 编程题实战从读题到AC的完整推演3.1 编程题整体风格与输入输出套路小米笔试的编程题是ACM模式需要自己处理标准输入输出而且提交后按测试用例得分不是“AC了就满分错了就0分”。所以即使是暴力解法只要部分用例能过也能拿到一些分数。两道编程题一般是一道DP、一道贪心或图论难度介于力扣中等和困难之间。数据范围比较大第一道题通常n在1000到10^5之间第二道题可能到10^5甚至更大。这种数据范围其实已经暗示了答案的复杂度要求不允许O(n^2)暴力过第二题必须用O(n log n)甚至O(n)。输入输出方面C建议直接用#include bits/stdc.h using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); // ...业务代码 return 0; }Python则建议用import sys def main(): data sys.stdin.read().split() # 然后用索引按顺序取数据 if __name__ __main__: main()这种批量读入方式在数据量大的时候比input()一行行读快很多能有效避免输入超时。3.2 模拟题一网格最小路径和动态规划题目大概是这样的给定一个 n x m 的矩阵每个格子里有一个非负整数从左上角出发走到右下角每次只能向右或向下走求路径上数字之和的最小值。数据范围 n, m 最大1000。这道题是非常经典的DP题。状态定义dp[i][j]表示从左上角走到(i, j)的最小路径和。转移方程dp[i][j] grid[i][j] min(dp[i-1][j], dp[i][j-1])边界条件是第一行只能从左往右走第一列只能从上往下走。这个思路很直接但如果只开一个二维数组在 n m 1000 时空间是 10^6完全没问题但如果数据范围再大一点就要考虑滚动数组优化。这里我给出一个更稳的写法直接用一维数组做空间压缩同时在读入数据时实时计算避免再开一个矩阵存储原始数据#include bits/stdc.h using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin n m; vectorlong long dp(m, LLONG_MAX); dp[0] 0; for (int i 0; i n; i) { for (int j 0; j m; j) { long long x; cin x; if (i 0 j 0) { dp[j] x; } else { if (j 0) dp[j] min(dp[j], dp[j - 1]) x; // 如果 dp[j] 是上一行传下来的不需要额外处理 } } } cout dp[m - 1] endl; return 0; }严格来说这个写法是“边读边推”省掉了存储矩阵的步骤。笔试时除非内存给得很小否则直接用二维数组也不会有问题。但提交前你最好确认一下题目数据范围如果 n 和 m 都到 10^5那就不能用二维DP得思考是不是有其他解法比如把问题转化成最小割或者用贪心。实际上笔试很少出那么夸张的二维数据多数情况下二维数组是能过的。3.3 模拟题二会议室安排贪心 优先队列第二道题比较像面试里常考的“会议室II”。题意是给出一组会议的开始时间和结束时间问至少需要多少个会议室才能安排下所有会议。数据范围是 N 最大 10^5开始和结束时间是整数。这道题的正解是贪心加最小堆。先把所有会议按开始时间排序然后遍历每场会议。用一个小顶堆维护“当前正在开的会议的结束时间”。如果堆顶的结束时间小于等于当前会议的开始时间说明有会议室已经空闲就把它弹出让当前会议复用这个会议室否则说明所有会议室都还在占用只能新开一间。最后堆的大小就是最少需要的会议室数量。代码#include bits/stdc.h using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin n; vectorpairint, int meetings(n); for (int i 0; i n; i) { cin meetings[i].first meetings[i].second; } sort(meetings.begin(), meetings.end()); priority_queueint, vectorint, greaterint pq; for (auto [start, end] : meetings) { if (!pq.empty() pq.top() start) { pq.pop(); } pq.push(end); } cout pq.size() endl; return 0; }这道题我实际做的时候踩了一个小坑如果两场会议的结束时间等于另一场的开始时间是可以共用一个会议室的所以判断条件是pq.top() start注意是小于等于不是小于。还有一点数据范围给到10^5说明要求 O(n log n) 解法如果你看到堆就想到这个解法基本就稳了。3.4 编程题的提交与调试策略编程题最怕的不是不会写而是“思路对但没提交上去”。我总结了一套实战策略这个策略在这次笔试里帮我稳住了节奏第一步读完题先看数据范围判断期望复杂度。n 20 大概率是状压DP或暴力搜索n 1000 可以用 O(n^2)n 10^5 就要想 O(n log n)。这能帮你快速排除错误思路。第二步先写一个能跑的暴力版本拿部分分尤其是第二题暴力至少能拿到小数据用例的分。第一题如果思路清晰直接写正解如果卡住了先写下暴力再慢慢推导优化。第三步留出5到10分钟自测边界情况。包括n 1 的情况、所有元素相同的情况、最大值和最小值的情况。这些边界用例在赛后复盘中非常常见但考场上很多同学因为时间紧张直接跳过结果在看不到的测试数据上丢分。4. 综合题与场景设计题容易被忽略的“软实力”4.1 场景设计题怎么答才能拿高分小米笔试的简答/场景题不是简单的背诵题它会给一个业务场景让你完整设计一套算法方案。今年第二批的大致场景是在一个短视频信息流产品里面对新注册用户没有行为数据的冷启动问题如何做内容的召回、排序和推荐策略。这类题目没有标准答案但阅卷人会看你的答题框架是否完整。我总结了一个比较通用的四段式结构确定目标、拆解流程、选择方案、评估迭代。先确定目标冷启动用户推荐的短期目标是让用户尽快产生点击或互动行为长期目标是留存和时长。所以需要明确评估指标比如点击率、人均播放时长、次日留存。接着拆解流程推荐系统一般分召回和排序两个阶段。冷启动用户没有行为数据所以不能依赖协同过滤要考虑基于内容的召回比如用户注册时选择的兴趣标签、手机品牌、年龄段、地理位置等基础画像信息做规则召回和向量召回混合策略。然后选择方案冷启动推荐可以用聚类算法先对用户分群比如把用户按注册设备、注册时段、画像标签聚成若干类在新用户进入时匹配最近的用户群然后推荐该群体热门或高转化的内容。排序阶段可以用XGBoost或者深度排序模型但冷启动阶段特征稀疏要加入更多语境特征比如时间、位置、设备。如果追求实时性还可以提到用多臂老虎机算法做探索与利用的平衡。最后评估迭代先小流量A/B测试用一组老用户作为对照观察新用户点击率、次留等指标是否显著提升再决定是否全量上线。这样答下来至少在逻辑完整性上是及格的。要注意的是不要只堆模型名字要解释清楚“为什么这个环节选这个模型”以及“数据量不够时怎么处理”。4.2 简答题高频点概念对比与原理推导简答题部分这次没考太偏的内容核心还是几个经典问题比如“XGBoost和GBDT的区别”“Batch Normalization为什么有效”“L1正则化为什么能产生稀疏解”。答这类题的时间控制在15分钟内尽量分条写。比如“BN为什么有效”不要只写“可以加速训练、防止梯度消失”要从以下几个角度展开BN对每个mini-batch在通道维度上做归一化让激活值保持在敏感区间它削弱了网络中间层对初始参数尺度的依赖这在一定程度上缓解了内部协变量偏移BN还引入了两个可学习参数保证网络可以恢复原始分布此外BN还带了轻微的正则化效果因为mini-batch的统计量有随机性。如果遇到需要推导的题目比如手写Softmax梯度一定要把链式法则写清楚分两步先求损失对Softmax输入的梯度再分析它与输出概率之间的关系。这类题目的关键不是计算多难而是要让阅卷人看到你有推导能力。4.3 笔试中的“时间管理学”一道完整的场景设计题从读题到写完大概需要15到20分钟。很多同学在选择题上花太多时间导致后面编程题和简答题时间不够这是笔试的大忌。我自己的时间安排是拿到试卷后先把所有题目扫一遍尤其是两道编程题看看难度差异决定先做哪道。然后笔试选择题控制在每题2分钟内。如果某道选择题超过3分钟还没思路直接凭第一感觉选并标记一下即使时间富余也不会回头细想因为选择题的容错率比较低但编程题一题就是25分性价比明显更高。简答题放在编程题之后做因为场景题再怎么写也就20分编程题AC一道就是25分先拿大头。如果你在编程题上卡死了也要尽快跳到场景题写几句确保不交白卷。说白了笔试是“在有限时间内拿最多分”的考试不是“每道题都完美”的考试。5. 常见问题与避坑指南这些坑我替你踩过了5.1 笔试环境与工具准备清单在线笔试最怕设备问题但每年都有同学在设备上翻车。我建议在考试前按这个清单检查一遍电脑电源要插上不要只用电池摄像头和麦克风权限要提前授权给浏览器手机的二机位要充满电并设置为常亮准备好身份证件浏览器建议关掉所有无关插件和弹窗网线比Wi-Fi更稳定有条件就插网线。还有一个细节很多在线笔试平台会在考试开始时进行一次人脸识别如果识别不通过需要拍照上传等待人工审核这个过程会占用考试时间。所以要提前把刘海梳起来摘掉口罩光线要充足不然卡在这几步很浪费时间。另外本地IDE里写的代码要能直接运行调试。我建议用本地IDE把代码调试通过后再往网页编辑器里粘贴但粘贴后一定要再运行一次用例因为平台可能对代码做了一些处理直接复制可能带入不可见字符导致编译失败。5.2 答题过程中的低级错误与典型案例这里整理几个真实发生过的低级错误错误类型典型案例避免方法数据范围判断失误矩阵乘法结果用int存溢出变成负数看到累加、求和、乘法直接用long long边界条件遗漏合并区间时忘记处理空输入每个算法题都过一遍 n0, n1 的用例输入输出格式错误输出多了空格或换行被判格式错误严格按照题目说明输出不要自作多情加提示语堆栈溢出递归深度达到10^5导致栈溢出深度大的搜索改成迭代栈或循环切屏被警告考试过程中切出去查看IDE插件考试前把所有工具准备好全程不切屏其中输入输出格式错误是最亏的代码逻辑全对结果因为多打印了一个“请输入n:”被判0分这属于需要坚决避免的失误。5.3 笔试评分视角与后续面试衔接笔试结束后我有一次机会和一位参加面试的同学沟通了解到小米的面试官在面试时是会看到笔试记录的包括编程题的提交代码和得分。这意味着笔试代码的风格比如变量命名是否清晰、注释是否简洁、有没有明显的边界漏洞都会被面试官看到。所以笔试过程中不要只追求“调试通过就提交”要尽量写出有可读性的代码。哪怕是暴力解也要把变量名写清楚把关键逻辑用一行注释说明。面试官看你的笔试代码时判断的不仅是你会不会这道题更是你在真实工程中写代码的规范性。笔试复盘也很有价值。考试结束后我把自己错的选择题和卡住的编程题重新整理了一遍发现大部分错误都来自对边界条件的忽视和对数据范围不够敏感。如果没有这一轮复盘后续面试里被问到类似问题时我可能还会在同一个地方栽跟头。5.4 给下一届考生的特别建议最后再针对准备参加算法岗秋招的同学说几句掏心窝的话。不要只刷力扣的hot 100笔试选择题覆盖的知识面要比单纯刷题广很多尤其是机器学习和深度学习理论建议把西瓜书或同等教材的课后题过一遍。编程题要尽早适应ACM模式刷力扣时可以用自定义输入输出来练习因为很多人写核心函数没问题一让处理输入输出就手忙脚乱。还有就是平时刷题要养成“先看数据范围再想算法”的习惯。很多时候笔试的题目难点不在于算法的名字有多高级而在于能否从数据范围反推正确的时间复杂度。这个习惯不是一朝一夕能养成的但一旦养成笔试答题会顺手很多。