说来也巧,最近后台有读者翻出我早年整理的滴滴出行秋招算法岗笔试复盘,问我还留着没有。翻出来看了看,发现这份材料即便是放在现在,对准备大厂算法岗笔试的同学依然有参考价值。滴滴的算法岗笔试在当年以“覆盖面广、题量适中、单题挖得深”著称,不像有些厂纯刷LeetCode,也不像另一些厂纯考机器学习理论,它更像是把数据结构、图论、机器学习、深度学习、场景建模揉在一起的一张综合卷。
我当时整理这份汇总时,特意把每道题的题型、考察点、可复现的思路都做了标注。这篇文章就是基于那次汇总的全面回顾,配合近年热门的算法考点做了一层扩展,希望能帮你少走点弯路。
1. 先从试卷结构说起:算法岗笔试到底考什么
1.1 题型分布与时间节奏
滴滴2017秋招算法岗笔试是典型的在线笔试,时长一般在90分钟到120分钟之间。从考生回忆版来看,题量通常在10到12道左右,但不会全是编程题,而是分成了三类:
| 题型 | 大致题量 | 占比 | 考察重点 |
|---|---|---|---|
| 单选题 | 4-6道 | 30%-40% | 数据结构、算法原理、机器学习基础 |
| 编程题 | 2-3道 | 30%-40% | 字符串处理、图论、贪心/动态规划 |
| 简答/场景题 | 1-2道 | 20%-30% | 业务建模、算法选型、优化思路 |
时间分配上,我个人建议把单选题控制在20分钟内,编程题留足50分钟以上,场景题最后用15到20分钟写框架即可。很多同学栽就栽在单选题上纠结太久,导致编程题没时间调试。记住一个原则:在线笔试的得分效率比单题完美更重要。
1.2 命题基调:为什么看起来像“大杂烩”
滴滴的算法岗笔试之所以看起来“杂”,根子上是因为算法团队分多条线:有做推荐搜索的,有做地图路径规划的,有做运筹优化的,还有做语音图像信号处理的。不同业务线共用一套笔试题,自然会把各自关注的基础能力都塞进去。
所以这份卷子透露出来的信号是:滴滴更看重候选人有没有“算法全栈意识”——既能手写KMP,也能聊清楚XGBoost的增益计算,还能对一个开放业务问题给出分步骤的解决思路。这也是我后来给学弟学妹做辅导时反复强调的:如果只刷LeetCode,不去补机器学习基础,很容易被单选和简答拖垮。
2. 被反复用来“卡人”的数据结构与字符串题
2.1 KMP与next数组:当年最经典的送命题
热词里有“在KMP算法中,对于模式串p=‘abacaba’,其next数组(next[i]定义为...)”——这基本就是滴滴当年选择题的原型或者近亲。KMP几乎是所有大厂笔试的“常青树”,但滴滴考得更细,不是让你背模板,而是直接给你一个具体模式串,让你算next数组。
以p="abacaba"为例,next数组有两种常见定义:一种是next[i]表示“模式串前i个字符组成的子串中,最长相等前后缀的长度”;另一种是next[i]表示“失配时跳转的位置”(通常为最长相等前后缀长度减一)。如果你不先明确题目用的是哪种定义,答案可以直接差出1。
计算过程我拆给你看(按next[i]为最长相等前后缀长度的定义):
- i=0:规定next[0] = -1或0,看题目约定。
- i=1:子串"a",无真前后缀,长度0。
- i=2:子串"ab",前缀集合{a},后缀集合{b},无交集,长度0。
- i=3:子串"aba",前缀{a,ab},后缀{a,ba},交集{a},最长长度1。
- i=4:子串"abac",前缀{a,ab,aba},后缀{c,ac,bac},无交集,长度0。
- i=5:子串"abaca",前缀{a,ab,aba,abac},后缀{a,ca,aca,baca},交集{a},长度1。
- i=6:子串"abacab",前缀{a,ab,aba,abac,abaca},后缀{b,ab,cab,acab,bacab},交集{ab},长度2。
- i=7:完整串"abacaba",前缀集合和后缀集合的公共部分为{a,aba},最长的是"aba",长度3。
所以按这个定义,结果为[-1,0,0,1,0,1,2,3](i从0到7)。如果把第一位约定为0,则是[0,0,0,1,0,1,2,3]。你只要在考场上先确认约定,再按“最长相等前后缀”的规则推一遍,基本不会错。
提示:很多同学背了getNext的模板,却不理解next数组是在“自己匹配自己”。真正理解之后,遇到任意模式串都能现场推导,远比背代码可靠。
2.2 排序与堆:从调用到实现原理的追问
选择题里还有一个高频方向是排序算法。热词里同时出现了“冒泡排序算法c++”“堆排序算法”“快速幂算法c++”,当年滴滴的卷子里也确实有类似题目:给定一个近乎有序的数组,问哪种排序算法实测最快;或者给出一组数据,要求手写堆排序的调整过程。
这类题真正的坑不在“会不会写”,而在“能不能说清原理”。比如堆排序,很多人只知道“建堆然后依次弹出堆顶”,但真让你对一个长度为n的数组建大顶堆,问你“为什么从n/2-1开始向下调整”,这里考的就是完全二叉树的性质——叶子节点不需要调整,从最后一个非叶子节点开始才能保证子树已经是大顶堆。
再比如快速幂,滴滴的编程题里如果出现求大数幂取模的裸题,本质就是在考快速幂。核心思路是把指数拆成二进制,靠着“每轮平方底数”的方式把时间复杂度从O(n)降到O(log n)。当年这道题本身不难,但很多人不知道用快速幂,直接写循环,小数据能过,大数据全超时。
2.3 贪心与动态规划的边界感
滴滴的编程题很喜欢考“看似能做贪心、实际必须动规”的题,以及反过来“看似可以动规、贪心更快”的题。这种题考察的就是你对问题结构的判断力。
举个例子,有一道回忆度很高的题:给定一组区间,问最多能选出多少个互不重叠的区间。这是经典的“区间调度”问题,按结束时间排序后从左往右贪心选即可,证明思路是“每次选择结束时间最早的区间,能为后续留出最大空间”。但如果你把它改成“区间带权重,选出的区间总权重最大”,贪心就失效了,得按结束时间排序后做动态规划。
我的建议是:考场上先花1分钟判断问题的贪心性质(是否有最优子结构、是否具有贪心选择性质),如果两个性质不满足,立即转DP。不要在一道题上同时纠结两种思路超过10分钟。
3. 图论与搜索算法:这些题其实是在考建模能力
3.1 Dijkstra与最短路径的变体
滴滴做地图和网约车调度,图论题几乎是必出的。热词里的“dijkstra算法”非常典型。但滴滴很少直接考裸的Dijkstra,通常是给一个业务场景,让你抽象成图再求最短路。
比如你可能会遇到这样一道回忆版题:城市里有N个路口,M条道路,每条道路有两个属性——通行时间和拥堵概率,求从起点到终点通行时间最短的路径。这里图节点是路口,边是道路,权重就是通行时间,直接Dijkstra。但如果题目再加一个约束:“要求整条路径的拥堵概率总和不得超过阈值”,那就不只是最短路了,得用带约束的图搜索或动态规划。
另外要留意Dijkstra使用的前提:边权非负。如果题目里出现了负权边,堆优化的Dijkstra会直接算出错误答案,这时候应该考虑Bellman-Ford或SPFA。这是个高频易错点,很多人刷题时没踩过这个坑,做笔试题就容易翻车。
3.2 二分图匹配与HK算法的思路
热词里的“二分图 hk算法”也让我想起来,滴滴的笔试选择题里确实出现过二分图匹配的概念题。HK算法(Hopcroft-Karp算法)是二分图最大匹配的优化版,通过BFS构建增广路径层数图,再用DFS寻找多条增广路,把复杂度从O(VE)优化到O(E√V)。
但说句实在话,笔试阶段不会让你完整写HK算法,最多考到概念层:比如“在二分图中,最大匹配数等于最小点覆盖数”这类等价定理,或者匈牙利算法的基本思想。真正需要手写HK的情况,一般是在面试阶段聊到极致优化时才会出现。
如果你是准备笔试,二分图这块掌握到能说明白“什么是增广路径”“匈牙利算法怎么找增广路”“HK相比匈牙利优化在哪”就足够;如果你是想冲更高级别的岗位,建议把匈牙利算法手写一遍,HK算法至少能讲清楚结构。
3.3 剪枝与启发式搜索的实用场景
搜索类题目在滴滴笔试里通常以“迷宫最短路径+障碍物动态变化”“棋盘上的最少移动次数”等形式出现。这类题表面是BFS,但如果你直接用裸BFS,往往会在大数据量下超时,这时候就轮到剪枝和启发式搜索出场了。
我记得有一道回忆版的题,大意是在一个网格里从起点走到终点,某些格子有代价,求最小代价路径。很多人条件反射就是Dijkstra,但如果你分析一下就会发现,当网格规模很大并且代价范围很小的时候,用双端BFS(0-1 BFS)甚至A算法会更快。A的关键是选对启发函数,比如曼哈顿距离作为估计值,只要估计值不大于真实代价,就能保证找到最优解同时减少搜索范围。
我在实际准备时养成了一个习惯:凡是看到“网格”“地图”“最短”这几个关键词,先不急着写代码,而是先在草稿纸上判断——是无权图还是有权的?是单源还是多源?是否适合加启发函数?这几个问题想清楚,代码往往10分钟内就能写完。
4. 机器学习与深度学习:笔试里的“算法”不只指数据结构
4.1 传统机器学习算法:从KNN到XGBoost
很多只刷题不学ML的同学会在这一块吃大亏。滴滴的算法岗笔试单选里,机器学习基础占的比例不低。热词里的“knn算法的应用能力包括哪三个方面”“机器学习算法”“xgboot算法”都指向这个方向。
KNN当年考过一道很典型的选择题:给定一组样本点和一个查询点,问取k=3和k=5时分类结果是否相同。这道题看起来简单,但考察了三个关键点:一是距离度量方式(欧氏距离还是曼哈顿距离),二是K值选取对决策边界的影响,三是投票时是否需要考虑距离权重。很多人只记得KNN是“看邻居”,却忽略了这三个细节,答案自然就错了。
XGBoost也是高频考点。滴滴业务中大量使用GBDT和XGBoost做排序和预估模型,所以笔试考到并不意外。常见考察点包括:XGBoost的目标函数由损失项、正则项和常数项构成;分裂时用贪心算法枚举特征取值寻找最优分裂点;正则项包含叶子节点数和叶子权重的L2范数,用来控制模型复杂度。如果你能说清楚“为什么XGBoost比普通GBDT多了二阶导数信息”,这道题基本就稳了。
顺带一提,“bm25算法”也出现在热词里。BM25是搜索引擎里常用的文本相关性排序公式,属于传统信息检索算法。如果笔试涉及推荐搜索方向,BM25这类文本匹配算法也可能会出现在选择题或简答题中,至少要知道它是对TF-IDF的一种改进:引入了文档长度归一化和词频饱和函数。
4.2 聚类与无监督学习的高频点
“聚类算法”在滴滴笔试里也不止一次出现。滴滴的乘客分群、司机调度、异常检测等场景都会用到无监督方法。K-Means是最常考的,但如果只背“随机选K个中心点,迭代更新”这个流程,遇到稍深一点的题就容易翻车。
常考的细节包括:
- K-Means算法一定能收敛到全局最优吗?不是,它只能保证收敛到局部最优,所以需要多次随机初始化选最好结果。
- 如何选择K值?常用手肘法和轮廓系数,但笔试题可能让你根据聚类结果反推K。
- K-Means对初始中心敏感,对离群点敏感,对非球形簇效果差,这些局限性要能展开说。
相比之下,DBSCAN这种基于密度的聚类方法在异常检测场景里更实用,因为它不需要提前指定簇数,还能自动识别噪声点。滴滴笔试里如果给一个“找出异常聚集区域”的场景题,用DBSCAN的答题思路明显比K-Means更贴合业务。
4.3 深度学习与强化学习的入门级考察
深度学习方面,滴滴的笔试更偏向考概念和应用。热词里的“深度学习算法”“强化学习算法”“kl elbo算法原理详解”都与此相关。
KL散度与ELBO的考点通常是这样的:在变分自编码器(VAE)中,ELBO是证据下界,等于重构似然期望减去KL散度项,训练过程就是最大化ELBO。你可能不会在滴滴笔试里遇到特别深的推导题,但“为什么VAE要引入重参数化技巧”“KL散度为什么是不对称的”这类概念题出现概率不低。记住一句话:KL散度衡量的是两个概率分布的差异,但它不是距离,因为不对且不满足三角不等式。
强化学习也偶尔出现在笔试中,比如问“探索与利用的平衡”:epsilon-greedy策略中,epsilon过大或过小分别会导致什么问题。这类题不要求你完整推导Q-learning更新公式,但至少要理解状态、动作、奖励、策略四个基本要素。
5. 场景题与开放题:拿到分和拿不到分的差距在哪
5.1 从粒子群到模拟退火:优化算法在业务里的应用
滴滴笔试的场景题有时候会跳出常规“机器学习八股”,直接给你一个运筹优化问题。热词里的“粒子群算法原理”“模拟退火算法”“剪枝算法”“井字棋minimax算法实现详解”等,都属于这个方向。
我记得有一道回忆版开放题,大意是:某个区域内有大量订单和司机,如何设计一个派单策略,使得整体接驾时间最短。这个问题没有标准答案,但答题时可以分层次展开:最朴素的方案是贪心——每个订单分配给最近的空闲司机;进一步是全局最优——把订单和司机建模成二分图,用KM算法或匈牙利算法求最小权完美匹配;再进一步,如果约束条件多了(司机会拒单、订单有截止时间),那就需要引入启发式搜索或模拟退火、粒子群等元启发式算法,在可行解空间里搜索近似最优解。
粒子群算法(PSO)的核心理解方式很简单:把每个候选解看成一只“鸟”,每只鸟有自己的位置和速度,通过向个体历史最优和群体历史最优方向飞行,逐步逼近全局最优解。笔试里如果出现PSO,大概率是问“PSO与梯度下降的区别在哪里”,核心答法是:梯度下降利用导数信息做确定性更新,PSO不依赖梯度,用群体协作的随机搜索去逼近最优解,适合非凸、不可导的优化问题。
模拟退火算法的思想也类似:以一定概率接受比当前解更差的解,避免陷入局部最优。这个“概率”随着温度下降而减小,最终收敛到近似全局最优。如果你能在场景题里提到这两个算法的适用场景,会让阅卷人觉得你有工程全局观。
5.2 实时系统与信号处理类题目的出现方式
滴滴做车联网和语音交互,对信号处理和实时控制算法也有需求,所以热词里的“卡尔曼滤波算法”“pid算法”“音频重采样算法”“图像锐化的拉普拉斯算法”等,在笔试的单选题里偶尔会出现。
卡尔曼滤波是GPS定位和传感器融合里的经典算法。考法一般是:在一个动态系统中,已知状态转移矩阵和观测矩阵,如何融合预测值和观测值。核心公式不用全背,但你要理解它的两个步骤——预测(根据上一时刻状态推断当前状态)和更新(结合当前观测修正预测值),以及“卡尔曼增益”是在预测不确定性和观测不确定性之间做权衡。
PID算法则是控制领域里最常用的闭环控制算法。考法通常是:在某个控制系统中,增大比例系数P会加快响应速度但同时增大超调量,增大积分系数I可以消除稳态误差但可能引起震荡,增大微分系数D可以抑制超调但对噪声敏感。这道题几乎是送分题,但如果你没接触过控制系统,确实会完全懵掉。
提示:这类题不需要你完整推导公式,但你要具备“用物理直觉理解算法行为”的能力。我在备考时把卡尔曼滤波、PID、傅里叶变换的基本思想都过了一遍,事实证明非常值得。
5.3 开放题的答题框架
开放题是最能拉开分差的题型。很多同学遇到开放题就懵,不知道从哪下手。我总结了一个百试不爽的答题框架:
- 明确目标:先写出你要优化的指标是什么(比如接驾时长、成交率、用户满意度)。
- 拆解约束:列出所有实际约束条件(司机数量有限、订单有时间窗、用户偏好等)。
- 给出基线方案:先说一个最简单的可行方案(贪心、规则匹配)。
- 提出优化方案:在基线方案上做增量优化,可以用匹配算法、机器学习模型、运筹优化等。
- 说明评估方式:怎么离线评测、怎么做A/B实验、关注哪些指标。
这个框架不一定让你拿到满分,但能保证你在有限时间内输出一个结构完整的答案,而不是写两行词不达意的句子。
6. 复盘后的备考建议与踩坑记录
6.1 时间分配的实战经验
我当时模拟练习时给自己定的规矩是:单选题25分钟内必须交卷,编程题每题40分钟,如果45分钟还没调通就先写暴力版本保底,场景题留15分钟写框架。这套策略在滴滴笔试里帮了我大忙——因为有一道编程题我用Dijkstra的变体写了25分钟没跑通,果断改成暴力BFS拿到了部分分数,最后总分反而比死磕到底要好看。
还有一点要提醒:在线笔试的编译器通常比较“死板”,不支持很多C++新特性,如果你平时习惯用Python刷题,遇到C++环境可能会手生。建议在笔试前至少用目标语言把KMP、堆排序、Dijkstra、二分图匹配这四类模板各写一遍,手熟了心态才会稳。
6.2 哪些知识点容易被轻视
从热词和当年笔试的对比来看,有几个知识点容易被刷题党忽略:
- 快速幂:看似简单,但结合矩阵快速幂就是斐波那契数列优化的基础,很多编程题里它是个隐藏前置技能。
- 音频/图像算法:如果你不是做信号处理方向的,可能觉得很偏,但滴滴确实有相关业务线,考到拉普拉斯算子、重采样这类题并不奇怪。
- 剪枝算法:搜索问题里剪枝是永恒的主题,从Alpha-beta剪枝到回溯法的剪枝条件,都属于低概率但高区分度的考点。
- BM25等检索算法:如果投的是推荐搜索方向,这类内容必看。
6.3 对后续面试的衔接建议
最后说一点关于笔试和面试衔接的事。滴滴的笔试不会只看总分,面试官在后续面试中可能会直接拿着你的笔试答卷来问:“你当时这道题是怎么想的?”如果你笔试时用了某种取巧方案,面试时却说不清楚原理,反而会减分。
所以我的习惯是:做完笔试题后,不管有没有AC,都会把每道题的思路整理成一份文档,记录解题路径、时间复杂度、还有哪些可以优化的方向。这样即使笔试成绩不理想,面试时也能展示出“我一直在思考”的态度,这在后来的面试中真的帮到过我。
如果你正在准备算法岗笔试,希望这份复盘能让你少踩几个坑。哪怕你投的不是滴滴,里面涉及的KMP、Dijkstra、贪心与动规的边界判断、聚类算法、场景题框架,也都值得反复琢磨。