2024年秋招-小米集团-算法岗-第一批笔试
2024年秋招算法岗的笔试,小米算是启动比较早的那一批。我投的是算法工程师方向,第一批笔试做完之后最大的感受是:题目覆盖面比想象中宽,既考数据结构与算法基本功,也考机器学习深度学习理论,还夹带了不少工程落地相关的问题。这篇文章把这些考点、题型和踩过的坑整理出来,给后面几批笔试的同学一个参考。
先说结论:小米算法岗笔试的难度属于中上等,题量不小,时间有点紧。考察重点不是“偏题怪题”,而是基础是否扎实、代码写得是否熟练、对主流算法模型的判断是否清晰。如果你正在刷题或者正准备其他大厂算法岗笔试,这篇内容同样有参考价值。
1. 笔试整体情况与题型构成
1.1 考试时间与环境配置
小米秋招第一批笔试是线上进行的,使用牛客网平台。整体时间是90分钟,题量大概在30到40道之间。我当时抽到的卷子由三个部分组成:单选题、多选题和编程题。单选题大概15道左右,多选题10道左右,编程题两道。分值分布没有在页面里明说,但从题量和时间倒推,选择题至少占60%以上。
线上笔试最大的特点是不能回头改答案。选择题部分做完一题过一题,不能检查不能犹豫。这就对知识点的熟练度提出了要求,如果一道题需要想超过两分钟,基本可以判断这道题会挂。编程题倒是可以做完了反复调试,但总共两道题,时间花太多在选择题上,编程题就没时间了。
一个比较坑的细节:牛客网笔试环境支持本地IDE和在线编辑器切换,但代码提交后编译报错不算分。我遇到过同学把本地能跑的代码粘到在线编辑器后,因为头文件缺失导致编译失败的情况。所以平时练习一定要养成在牛客或者力扣环境里提交代码的习惯。
1.2 题型范围与考点分布
从我做过的题和其他参加第一批笔试同学的反馈来看,小米算法岗笔试的考点分布大致如下:
- 数据结构与算法基础:数组、链表、栈、队列、树、图、排序、搜索、动态规划、贪心,约占总題量的40%
- 机器学习与深度学习理论:损失函数、模型评估指标、常见模型原理、优化器、正则化,约30%
- 算法综合应用:工程场景题、策略设计题、数学推导题,约20%
- 编程题:两道代码题,占剩余10%的分值,但实际难度和区分度最高
这里要特别强调一下,行业里常见的“算法岗笔试只考机器学习”这个印象其实不太准确。小米这批笔试明确考了大量数据结构与算法的内容,包括KMP算法、堆排序、图的遍历这些经典题目,而且考得比较细。所以备考的时候“算法基础+机器学习”两条腿都要硬,只押一头容易翻车。
2. 核心算法考点拆解与备考要点
2.1 数据结构与基础算法:不只是刷题,更要懂原理
这批笔试在数据结构部分考得挺细的。我印象比较深的一道题是关于KMP算法的next数组,给了一个模式串,让计算next数组的值。这道题考察的不仅是背代码,而是真正理解KMP的原理。很多同学刷题时知道KMP比暴力匹配快,但为什么快、next数组怎么递推,就说不清了。
KMP的核心思想是利用已经匹配的部分信息,让模式串在失配时尽量向右滑动更多距离,避免主串指针的回退。next数组记录的是模式串每个位置之前的子串中,最长的相同前缀后缀长度。举个简单的例子,模式串abacaba的next数组,手工推导的要点是:
a前面没有子串,next值为0ab没有相同前后缀,next值为0aba有最长相同前后缀a,长度为1abac没有相同前后缀,next值为0abaca有相同前后缀a,长度为1abacab有相同前后缀ab,长度为2abacaba有相同前后缀aba,长度为3
笔试时这类题不会让你写整个算法,而是给你几个关键位置让你求值,要么就是判断某个步骤的工作原理。但如果你只会“背模板”,遇到稍微变形就露馅了。我的建议是,数据结构部分的每个算法,至少要能达到“手推一遍执行过程”的程度,而不是只看代码。
2.2 排序算法:复杂度、稳定性、适用场景的辨析
排序算法是选择题的重灾区,几乎每年必考。今年小米这批笔试题里就有一道关于堆排序的应用题:给定一个无序数组,要求用堆排序求前K个最小元素,问时间复杂度和空间复杂度各是多少。
这类题的常见误区是把堆排序和堆的建堆过程混为一谈。堆排序本身的时间复杂度是O(nlogn),但求前K个最小元素用堆实现的话,建一个大小为K的大顶堆,遍历数组依次维护堆,整体时间复杂度是O(nlogK),空间复杂度是O(K)。如果你在选项里看到了O(nlogn)以为是无脑选,就掉坑了。
关于排序算法,比较推荐把以下要点整理成表格:
- 冒泡排序:稳定,O(n²),最好O(n),适合基本有序的小规模数据
- 快速排序:不稳定,平均O(nlogn),最坏O(n²),工程中最常用的排序算法
- 归并排序:稳定,O(nlogn),需要O(n)额外空间,适合链表排序和外部排序
- 堆排序:不稳定,O(nlogn),原地排序,适合海量数据TopK问题
- 计数排序/桶排序/基数排序:非比较排序,桶排序在数据均匀分布时可达到O(n)
笔试考排序,核心是考你“在什么场景下选什么算法”的判断力。比如数据量巨大但取值范围很小,计数排序远优于快速排序。这个决策能力比手写某个排序更接近真实工程中的情况。
2.3 贪心算法与动态规划:边界条件和递推关系
编程题和选择题中,贪心与动态规划都是重点项目。小米这批笔试的选择题里有一道经典的贪心应用题——区间调度问题:给定若干区间的起止时间,求最多能选择多少个互不重叠的区间。这个问题的标准解法是按照结束时间排序,然后贪心地选。
如果是编程题遇到动态规划,最容易丢分的点不是递推写不出来,而是边界条件处理错了。以经典的“最长递增子序列”为例,很多同学会忘记初始化dp数组为1,导致长度为1的序列输出0。这类细节就是笔试的区分点。
动态规划考察的核心是“状态定义”和“状态转移”。我个人的做题习惯是,拿到题目先不急着写代码,先用一句话说清楚dp[i]表示什么,再想dp[i]怎么从之前的状态转移过来。如果状态定义清楚了,转移方程基本就是抄一遍的问题。
2.4 机器学习与深度学习理论:模型原理和评价指标
机器学习理论在小米算法岗笔试里占比不低。印象比较深的一道多选题,问的是关于梯度下降优化器的描述,哪些是正确的。选项涉及SGD、Momentum、RMSProp和Adam。这道题如果只是知道名字,根本选不对,必须了解每个优化器的更新公式和特性。
给大家几个考点整理:
- 损失函数与风险函数的关系,交叉熵与KL散度的联系
- 精确率、召回率、F1、AUC的定义和适用场景
- L1正则化为什么会产生稀疏解,L2正则化为什么能防止过拟合
- SVM的核函数选择、软间隔含义
- 决策树的信息增益、信息增益率、基尼系数
- 随机森林与GBDT的区别,Bagging和Boosting的本质差异
- 梯度消失和梯度爆炸的原因及常见解决方案
- 常见的激活函数及其导数形式,ReLU为什么会死神经元
我笔试时遇到的一道比较综合的单选题:给定一个二分类问题,1000个样本中有950个正样本和50个负样本,问在AUC和准确率两个指标中,哪个更不适合作为评价指标,以及原因。答案是准确率不适合,因为当正负样本极不平衡时,模型把所有样本都预测为正类,准确率仍然高达95%,掩盖了模型对负类的识别能力。这类题不算难,但需要平时理解指标的本质,而不是背AUC的取值范围。
2.5 算法综合应用:策略设计题和数学题
除了常规考点,小米这批笔试还出现了一些综合应用题。比如有一道场景题:在电商推荐场景中,如何对一个用户在一个月内的访问序列进行异常检测,要求给出算法思路和时间复杂度。这类题属于开放设计题,没有标准答案,但考察的是你能否把学过的算法迁移到真实业务里。我当时答的是基于统计规则的方法,比如滑动窗口计算访问频率的历史均值和标准差,如果当前窗口的频率超过均值加三倍标准差,就判定为异常点。本质上就是简单的异常检测思想。
这类题没有绝对的对错,重要的是逻辑自洽。建议答题时先说明场景特点,再给出算法选择理由,最后补充复杂度和边界情况处理。这种结构化表达在算法岗面试和笔试中都是加分项。
3. 笔试实操:编程题的完整答题流程
3.1 题目类型与难度分析
编程题部分通常会给出两道算法题,难度在力扣中等偏上。我这次遇到的两道题,一道是“数组中的最長连续子序列长度”,要求时间复杂度尽可能低,另一道是“二叉树的层序遍历变种”,需要返回自底向上的层序结果。
两道题都不算冷门,但因为时间受限,如果第一遍没有很快想出思路,就很容易慌张。所以这里想分享一下我梳理出的答题流程,每个步骤对应时间分配也有参考价值:
- 阅读理解题目,提取输入输出格式,耗时2-3分钟
- 确定算法框架(暴力法还是优化法),写出伪代码思路,耗时3-5分钟
- 编写代码,注意变量名和边界条件,耗时10-15分钟
- 用简单的测试用例自测,包括边界情况,耗时5分钟
- 提交前检查数据范围是否可能溢出,耗时2分钟
3.2 典型编程题解题过程与代码参考
以“数组中的最长连续子序列”为例,这道题要求不改变原数组顺序,从中选出若干个数组成一个长度最长的子序列,保证这些数在原数组中的相对顺序不变,且数值严格递增。这道题最常见的解法是动态规划,时间复杂度O(n²),但题目如果数据范围到10^5,这个复杂度会超时。
状态定义:dp[i]表示以第i个元素结尾的最长递增子序列长度。 状态转移:对于每个j小于i,如果nums[j] < nums[i],则dp[i] = max(dp[i], dp[j] + 1)。 边界条件:每个位置初始化为1。
但如果只按这个思路写,遇到大量数据时过不了。优化的方向是用贪心加二分:维护一个tails数组,tails[k]表示长度为k+1的递增子序列中末尾元素的最小值。遍历每个数,在tails里二分找到第一个大于等于当前数的位置并替换。这样时间复杂度降为O(nlogn)。
下面用C++实现这个优化版本:
#include <bits/stdc++.h> using namespace std; int lengthOfLIS(vector<int>& nums) { vector<int> tails; for (int x : nums) { auto it = lower_bound(tails.begin(), tails.end(), x); if (it == tails.end()) tails.push_back(x); else *it = x; } return tails.size(); } int main() { int n; cin >> n; vector<int> nums(n); for (int i = 0; i < n; i++) cin >> nums[i]; cout << lengthOfLIS(nums) << endl; return 0; }注意:这里用的lower_bound是标准库的二分查找,返回第一个不小于x的位置。把x替换为更小的值,保证了后续更长的子序列可以接上。这个技巧笔试时如果能写出来,是明显的加分项。
3.3 时间分配策略:选择题控制在60分钟内
编程题虽然占比不算大,但非常影响心态。我的建议是:如果选择题已经做了40分钟还没有做完,果断放弃剩余的选择题,先花20分钟把编程题的第一道做出来。因为一道编程题的通过率比五道选择题还值钱,而且编程题写完了心态会比较稳。
整体时间分配可以参考:
- 单选题:20分钟,平均每题1分钟左右
- 多选题:25分钟,平均每题2分钟左右
- 编程题第一题:25分钟
- 编程题第二题:20分钟
如果选择题卡住了,千万不要恋战。线上笔试的选择题一题过了就过了,多纠结两分钟,后面编程题就少两分钟。我第一道多选题想了三分钟,后面编程题差点没写完,这个教训希望大家不要重演。
4. 备考路线与做题策略:秋招笔试怎么准备
4.1 刷题优先级与经典算法清单
如果准备时间有限,先刷以下高频内容:
- 数组与字符串:双指针、滑动窗口、前缀和、二分查找
- 链表:反转链表、快慢指针、链表相交
- 树:二叉树的遍历(前中后序、层序)、树的最大深度、最近公共祖先
- 图:拓扑排序、DFS与BFS遍历、最短路径(Dijkstra、Floyd)
- 动态规划:背包问题、最长回文子序列、编辑距离
- 贪心:区间调度、跳跃游戏、分发饼干
- 排序:快速排序、堆排序、归并排序的手写
- 字符串:KMP、Trie树、字符串哈希
- 机器学习算法:聚类算法K-Means、KNN分类、朴素贝叶斯、线性回归与逻辑回归
小米笔试多选题中有一道关于K-Means聚类算法的题,问的是哪些操作可以改善聚类效果。正确答案包括选择合适的K值(如使用肘部法则)、采用K-Means++进行初始化、多次运行选择最小的SSE等。这道题不算难,但提醒我们算法不能只刷数据结构,机器学习算法原理也要啃扎实。
4.2 手撕代码的训练节奏
编程题训练建议按照“三遍法”来做:
- 第一遍:看题后尝试独立思考,如果20分钟没有思路,直接看题解,弄清核心思路就好
- 第二遍:看完题解后合上书或网页,自己完整写一遍,写到能通过所有测试用例为止
- 第三遍:隔天不看任何参考,手写完整代码,重点检查边界条件和时间复杂度
这个节奏比“一天刷十道但每道都看题解”要有效得多。真实笔试时,没有题解可看,平时不训练“独立完整输出代码”的能力,考场上就会大脑空白。
4.3 注意米哈游字节等大厂笔试中的算法岗通用能力
虽然标题是小米,但秋招笔试的考查逻辑在各家之间其实是共通的。投递小米的同时基本上也会投字节、腾讯、美团、阿里等公司,而各家算法岗笔试的共性大于差异:
- 数据结构与算法是必考的,题量可能不同但占比都高
- 机器学习和深度学习理论越来越受重视
- 编程题都是两道左右,难度在力扣中等区间
- 线上笔试平台以牛客为主,少量用赛码
所以我个人的建议是,不用针对某一家公司单独准备,而是按“算法岗通用笔试”去做准备。把力扣热门100题刷完,再补一遍机器学习的核心概念,基本能够覆盖80%以上的考点。剩下的20%靠临场发挥和心态。
5. 线上笔试的实战细节与避坑经验
5.1 编码习惯与自测技巧
编程题最容易丢分的地方不是算法不会,而是细节出错。我总结了几个使用本地IDE和在线编辑器时需要注意的坑:
输入读取不完全。某些题目有多组测试用例,如果代码只处理了一组就输出结果,得分会很低。建议使用while循环读取,直到EOF为止。
数组越界和内存溢出。尤其是动态规划题目,如果开数组大小为n而不是n+1,访问dp[n]时就会越界。笔试环境不会给很友好的报错信息,可能直接显示运行错误,容易手忙脚乱。
浮点数比较问题。题目要求保留六位小数,有的人直接printf("%.6f", ans),但没有处理浮点误差。建议在比较浮点数时加上一个很小的epsilon值,比如1e-8。
提示:编程题提交后只能看到通过率,不显示具体错误用例。如果通过率不是100%,优先检查边界条件,比如空数组、单元素数组、全部相同元素的数组。
5.2 时间管理与心态调整
线上笔试和线下面试不同,没有面试官提醒时间,也没有交流环节。页面右上角的倒计时一旦开始,就只能靠自己掌握节奏。我个人的策略是:
- 前30分钟专注做选择题,不纠结不纠结再纠结
- 30分钟到45分钟:做第一道编程题
- 45分钟到70分钟:做第二道编程题
- 最后20分钟:回头检查选择题中拿不准的题目(如果有时间)
当然这个节奏要灵活调整,如果第一道编程题很简单,15分钟就AC了,剩余时间就可以多花在选择题上。重点是不要因为某一道题卡壳,导致后面所有题都受影响。
5.3 多选题的技巧:宁少勿多
多选题的评分规则一般是漏选得部分分,错选、多选不得分。所以如果一道多选题目拿不准某个选项是否正确,最好不选。不要抱着“多选一个说不定能碰到”的侥幸心理,大概率会因此整道题零分。
举个例子,有一道关于过拟合解决方法的多选题。选项里有一个是“增加训练数据量”,一个是“降低模型复杂度”,一个是“提高学习率”,一个是“加入L2正则化”。前两个和最后一个都是正确的,但“提高学习率”这个选项有争议——学习率过大可能导致不收敛,但一定程度上它也起到了正则化的效果。如果你没有把握,就不要选学习率那个选项,保住其他三个选项的部分分。
这个策略帮我拿到了不少多选题的分,建议大家以后遇到类似题型都采用。
5.4 简历方向与笔试内容的匹配度思考
最后说一个不太常被提及的点:算法岗笔试的内容和你在简历上写的方向是有关系的。
如果简历是图像算法方向,笔试试卷会在机器学习理论之外多考一些图像预处理、卷积神经网络结构的内容。如果简历是推荐算法方向,可能多考一些用户行为序列建模、Embedding、多任务学习的内容。我当时投的是通用算法方向,所以试卷内容比较均衡。
这提醒大家,投递简历时方向一定要和自己的能力匹配。简历上写了三个方向,但每个方向都只有项目没有深度,笔试时反而容易出现“什么都考、什么都不熟”的尴尬。聚焦1到2个方向,把相应领域的经典算法吃透,效果会好很多。
6. 笔试后的复盘与下一步准备
不管笔试结果如何,考后24小时内做复盘是价值最高的。拿我自己的经验来说,笔试结束后我会立刻把自己记得的题目整理出来,对照答案判断对错,找出知识盲区,然后针对性地补充。这样做两三次之后,后续几家大厂的笔试通过率会明显提升。
对于不确定的选择题,可以在牛客网或者社区里找同批次笔试的同学讨论。笔试题目通常不会公布官方答案,但大家拼凑起来基本能还原考点和正确思路。这个过程也是积累解题思路的过程,比单纯刷题更高效。
还有一点,笔试只是秋招流程的第一步,后面还有面试。小米面试中经常会让手写代码和深挖项目,笔试中暴露出来的算法薄弱点,如果能在面试前补齐,反而是一次很好的查漏补缺机会。所以不要因为笔试没考好就灰心,关键是下次不再踩同样的坑。