ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

滴滴出行2016研发工程师笔试题深度拆解:算法与业务场景实战指南

滴滴出行2016研发工程师笔试题深度拆解:算法与业务场景实战指南 我还记得第一次拿到滴滴出行2016研发工程师笔试题二这份卷子时的感觉题目不算偏但每道题都透着一股“业务味儿”。同样是考数组、考动态规划滴滴会把场景往“订单”“路径”“高峰时段”上靠同样是考SQL恨不得让你直接统计出某个区域内每分钟的打车请求量。这套题之所以值得反复研究不只是因为它来自一家头部互联网公司更因为它代表了一种趋势笔试不再只是考察你会不会背算法模板而是考察你能否在真实出行场景里把数据结构和算法用对、用活。如果你是准备投递互联网公司研发岗位的应届生或者想跳槽去出行、交易、调度这类业务场景比较重的团队这套题是一个很好的复习坐标。它帮你把“算法刷题”和“工程落地”之间的缝隙看得更清楚。接下来我会按考点拆解这套题的出题逻辑把高频题型的解题思路、现场策略以及笔试后的面试延伸都梳理一遍尽量做到可以直接照着调整自己的复习计划。1. 这套题在考什么出题逻辑与考点地图1.1 为什么滴滴的笔试题值得认真做很多同学刷题喜欢盯着LeetCode按序号刷刷完觉得“题也做了不少怎么一到笔试还是慌”。我做这套题的时候最大的感受是它是典型的“业务驱动型笔试题”题目不是随便从题库里抽的而是围绕滴滴的核心业务逻辑设计的。滴滴的核心业务是什么是撮合。乘客发单、司机接单、平台派单本质上是在一个动态变化的时空环境里做供需匹配。这个业务特征决定了它对研发工程师的能力要求非常具体第一你要有扎实的算法功底因为订单分配、路线规划、价格预估背后全是算法第二你要能处理高并发场景早晚高峰和恶劣天气下订单量会瞬间飙升第三你要懂数据订单表、司机表、乘客表之间的关联查询是日常操作。这些能力笔试里全都会体现出来。所以说这套题不是简单考你“会不会写代码”而是考你“能不能用代码解决出行场景里的真实问题”。你在刷题时如果能带着“这个算法在滴滴的哪个环节会用到”这个问题去想收获会大得多。1.2 考点分布与题型结构从我接触到的信息和身边同学考完后的反馈来看滴滴出行2016研发工程师笔试题二的整体结构大致延续了互联网公司校招笔试的经典配置但权重分配很有自己的特点。考察方向常见题型大概占比复习优先级算法与数据结构数组、链表、字符串、栈、队列、二叉树、图论40%左右高动态规划与贪心背包、最长子序列、区间调度、状态机20%左右高数据库与SQL聚合查询、分组统计、表关联、索引优化15%左右中高操作系统与网络进程线程、死锁、TCP/UDP、HTTP10%左右中系统设计类短题设计订单模块、派单流程10%左右中语言基础C/Java内存管理、多线程、集合类5%左右中从这个分布能看出算法题占了绝对大头这一点和大多数互联网公司是一致的。但数据库和系统设计题的比例明显比其他纯互联网公司高这跟滴滴的业务属性高度相关。出行平台每天产生海量订单数据工程师不会写SQL、不懂表设计基本没法干活。所以如果你打算投滴滴这类出行公司复习的重点排序应该是算法精通为主数据库和系统设计必须会操作系统和网络基础也不能丢。这四个方向搞定了笔试这关基本就稳了。2. 算法题核心拆解从暴力解法到最优解2.1 数组与字符串边界条件比思路更重要数组和字符串是笔试题里最基础的题型但也是最容易翻车的题型。这套题里的数组和字符串题往往不会直接说“给你一个数组求最大值”而是会包装成一个业务场景。比如给出某个时间段内乘客的出发地和目的地坐标让你计算某个区域内的订单密度之类的。这类题表面考的是数组遍历实际考的是三个能力第一是滑动窗口的运用第二是前缀和的预处理第三是边界条件的处理。我见过很多同学思路完全正确但代码一跑就报错原因基本都是边界条件没处理好比如数组越界、空数组没判断、循环退出条件写错。拿滑动窗口来说很多数组题都能用暴力解法通过小数据测试但笔试的测试用例不会那么仁慈。以“找出数组中满足某条件的最短子数组长度”这类题为例暴力解法是两层循环时间复杂度O(n²)数据量一大就超时。滑动窗口的正确思路是用左右两个指针维护一个窗口右指针不断向右扩展当窗口内满足条件时尝试移动左指针缩小窗口记录最优解。这个思路在处理连续子数组问题时几乎通吃代码模板也很固定。再说边界条件。我个人的习惯是写代码之前先在注释里把三个问题写清楚数组为空怎么处理、只有一个元素怎么处理、目标值不在数组中怎么处理。这三个问题想清楚了代码的鲁棒性就有保障了。笔试的判题系统最喜欢用空数组、单元素数组这种极端用例来卡人很多同学不是不会做而是死在了边界条件的疏忽上。2.2 动态规划与贪心先定义状态再谈优化动态规划在滴滴这套题里出现的概率非常高。为什么因为滴滴的业务场景里到处都是“最优决策”的问题司机在某个位置接到订单后是去接乘客还是原地等待乘客从A点到B点是走高速还是走普通路这些问题的本质都是动态规划或者贪心算法能够处理的。做动态规划题我总结了一个固定套路按顺序完成四步基本能解决90%的动态规划题第一步定义状态。想清楚dp[i]代表什么。这一步是最关键的状态定义对了后面的转移方程就水到渠成。状态定义错了整个题就废了。第二步找出状态转移方程。想清楚dp[i]是怎么从之前的状态推导出来的。这一步需要你对问题的结构有清晰的理解。第三步确定初始化条件。dp[0]或者dp[0][0]是什么边界情况在递推开始之前要先设置好。第四步确定遍历顺序。是从前往后还是从后往前是单层循环还是双层循环这个必须和状态转移方程匹配。以经典的“最长递增子序列”为例dp[i]的定义是“以第i个元素结尾的最长递增子序列的长度”转移方程是“dp[i] max(dp[j] 1)其中j i且nums[j] nums[i]”。初始化时所有dp[i] 1因为每个元素自身就是一个长度为1的子序列。这里面最容易犯错的是状态定义不清晰尤其当题目包装了一层业务外衣后很多同学会被场景带偏直接去想业务逻辑而忘了抽象出数学模型。我的建议是不管题目描述多花哨先把它翻译成“输入是什么、输出是什么、约束条件是什么”一旦完成这个抽象动态规划就变成了一道纯粹的数学题。2.3 图论与搜索地图场景的标配考点滴滴做的是出行生意地图是基础设施所以图论相关的算法在笔试题里出现几乎是必然的。最经典的考点包括最短路径Dijkstra、Floyd、拓扑排序、并查集以及深度优先搜索和广度优先搜索框架的变体。以最短路径为例很多同学的第一个反应是直接背Dijkstra的模板。但笔试真正的难点不是背模板而是识别出“这道题其实是在求最短路径”。有时候题目描述是“给定一个城市地铁线路图求从起点站到终点站最少要坐几站”有时候是“给定一个订单派送网络求从一个配送站到另一个配送站的最小成本”。这些题本质都一样但如果你看不出来是图论问题就会陷入不知道用什么算法好的困境。我个人的习惯是拿到题目先画图。哪怕题目已经用文字描述了关系我也习惯在草稿纸上把节点和边画出来。这么做的好处是第一能直观判断这是不是图论问题第二能看出图的规模有多大从而决定是用O(V²)的朴素Dijkstra还是用O(E·logV)的堆优化版本第三能发现题目里是否藏着负权边或者环这些都会影响算法选型。并查集也是高频考点。它本身不是难题核心代码只要十几行但应用场景非常灵活比如“判断两个节点是否连通”“统计连通分量的数量”等。做这类题的关键是识别出“关系判断”的本质及时想到并查集这个工具不要用DFS去反复遍历。3. 数据库与系统设计滴滴最在意的业务能力3.1 SQL题订单统计中的聚合陷阱数据库在笔试中占的比例虽然不如算法高但对于滴滴这类出行公司来说SQL写得好不好直接反映了你有没有处理真实业务数据的能力。滴滴的业务数据天然是结构化的订单表、司机表、乘客表、车辆表各种表之间的关联查询是工程师每天都要做的事情。这套题里的SQL题常见的有这么几类一是聚合查询比如统计每个区域的日均订单量二是分组过滤比如找出订单量超过100单的司机三是表关联比如查询每个乘客最近的订单信息四是时间窗口比如统计每个小时内的订单分布。很多同学在写SQL时最容易犯的错误是把WHERE和HAVING混用。WHERE是在分组之前对原始记录进行过滤HAVING是在分组之后对分组结果进行过滤。举个具体的例子统计订单量超过100的司机必须先用WHERE过滤掉无效订单比如取消订单、测试订单然后按司机ID分组再用HAVING COUNT(*) 100筛选。如果把过滤条件写在WHERE里你会发现分组结果完全不对。还有一个高频考点是DISTINCT和GROUP BY的区别。DISTINCT是对查询结果去重GROUP BY是对数据进行分组然后做聚合运算。很多同学在统计不同乘客的数量时会写成SELECT COUNT(DISTINCT passenger_id)这个没问题。但如果需求变成“统计每个乘客的订单数”就必须用GROUP BY passenger_id了。搞清楚这两个的区别SQL题基本不会出大错。另外我建议你有时间的话自己建一个订单表往里插几百条模拟数据然后自己写各种查询练习。SQL这个东西没有捷径只有多写才能形成肌肉记忆。笔试现场时间紧张如果你还需要现场回忆某个函数怎么用那基本就来不及了。3.2 设计题怎么设计一个可用的派单模块系统设计题是这套题里比较有区分度的部分。它不要求你写完整代码而是考察你面对一个开放性问题时能不能给出一个结构清晰、有逻辑的方案。以“设计一个简单的派单模块”这类经典题目为例我的答题套路是分四步走。第一步明确需求。派单模块的核心目标是把订单分配给最合适的司机约束条件包括距离、司机状态、订单类型等。这里要注意面试官想看你是否能区分“核心功能”和“非核心功能”。第二步拆分模块。派单模块至少包含订单接入、司机匹配、结果推送、状态回写四个子模块。每个子模块的职责要清晰。第三步定义数据结构。订单需要存储哪些字段司机需要维护哪些状态司机和订单的匹配关系用什么数据结构保存第四步说明关键流程。比如订单进入系统后怎么找附近的司机怎么处理多个司机同时抢单司机拒绝订单后怎么办这个答题套路适用于大部分系统设计题关键是向阅卷人展示你的思维有条理而不是东一榔头西一棒子。做完这一步你还可以提一下高并发场景下的优化思路比如使用缓存、消息队列、读写分离等这些加分项在笔试里也能体现你的工程视野。3.3 高并发与性能笔试题里不会明说但一直存在的考点严格来说这套题里可能没有单独考高并发的题但很多题目都在暗示你需要有并发意识。比如SQL题里有一类“订单表数据量巨大怎么优化查询”的问题本质上就是在考索引和分表。系统设计题里的派单模块如果你只设计了单机版而没有考虑到高峰期的流量压力方案就是不完整的。滴滴的业务有一个很典型的特点明显的波峰波谷。早高峰和晚高峰的订单量是平峰期的几倍甚至十几倍这意味着系统必须具备弹性扩容能力。在笔试里体现这个意识的方式很简单在设计题中主动提到“热点区域订单集中”“订单同步延迟”“重复派单问题”等场景并给出对应的解决方案。哪怕方案不完美也能让阅卷人感受到你在思考真实问题。4. 笔试现场策略时间分配与避坑指南4.1 时间分配先拿稳分再冲难题滴滴这套题的整体题量不小正常情况下代码题加上选择题要在规定时间内全部完美做完是很有挑战的。我见过太多同学在前面的难题上死磕导致后面的简单题没时间做最后分数很难看。我的时间分配策略是这样的拿到试卷先花两分钟把所有题目扫一遍。把题目按“肯定会做”“需要想想”“完全没思路”分成三档。然后按照倒序来做先做“肯定会做”的确保基础分全部拿到再做“需要想想”的把能想到的思路写出来哪怕代码不是最优也要保证有正确输出最后剩下的时间才用来攻“完全没思路”的能写多少写多少。这套策略的核心逻辑是笔试题的分数分布是不均匀的简单题拿到的分数和难题一样值钱。很多同学总觉得难题做出来才有成就感但忽略了简单题错了更可惜。确保所有会做的题不丢分你的分数就已经超过大多数人了。4.2 代码规范与注释阅卷官真正想看到什么笔试的代码题阅卷人不仅看你的代码能不能通过测试用例还会看你的代码风格。这里说的代码风格不是“缩进用空格还是Tab”这种细节而是你的代码是否体现了工程化的思考习惯。我建议在笔试中注意以下几点第一变量命名要有意义。不要用a、b、tmp这类无意义的名字要用orderCount、driverId、minDistance这类能直接表达含义的名字。第二关键注释要写。不是为了凑字数而是在核心逻辑处用一句话说明你的思路这样阅卷人一眼就能看懂你在干什么。第三代码结构要清晰。能用函数拆分的就拆分不要把所有逻辑都堆在main函数里。第四异常情况要处理。输入为空、越界、除零这类问题好的代码会有防御性判断。这里面最容易被人忽视的是注释。很多同学觉得笔试时间紧注释不重要。但换个角度想如果你的代码没有通过所有测试用例阅卷人就会看你的代码来评估你的水平。如果代码逻辑清晰、注释明了即使有小bug阅卷人也会觉得你是个基础扎实的人如果代码又乱又没有注释即使通过了测试用例也未必能给阅卷人留下好印象。4.3 常见笔试翻车点速查表结合我自己的笔试经历和身边同学的反馈我整理了下面这些常见的翻车点建议你在进笔试考场之前过一遍翻车场景典型原因解决策略代码在大数据量下超时使用了O(n²)甚至更高复杂度的算法先看数据范围再选复杂度合适的算法空数组/单元素数组报错没有处理边界条件写代码前先列出边界条件SQL查询结果和预期不符WHERE与HAVING混用、空值未处理写完SQL后自己代入两行数据推演一遍系统设计题没有结构想到哪写到哪按“需求-模块-数据结构-流程”四步走前面难题耗时过多后面简单题没时间做没有先做会做的题扫卷后先做稳分题题目看错没注意到输出格式要求写完代码后回读一遍题目描述这份速查表可以打印出来放在手边笔试前翻一遍能有效避免低级失误。5. 笔试之后的面试延伸这套题如何帮你校准复习方向5.1 从笔试到面试为什么说笔试只是起跑线很多人以为笔试过了就万事大吉但实际上笔试只是筛选的第一关。滴滴的面试环节会更深入地考察你对技术原理的理解和实际工程能力。笔试里考的算法、数据库、系统设计这些内容在面试中会被进一步追问而且问题会更加开放。举个例子笔试中写了一个SELECT语句统计订单量面试官可能就会追问“这个查询在订单量达到千万级时怎么优化”“如果订单表高频写入索引会不会成为瓶颈”“你会怎么设计订单表的分表策略”这些问题的答案在笔试里是看不到的但如果你在准备笔试时就带着工程视角去思考面试的时候就不会被问懵。我建议你在准备笔试时不要只满足于“题做对了”而是每做一道题就多问自己三个问题这个算法有什么局限性这个方案在大数据量下还能不能工作如果并发量提高十倍我的设计需要做什么改动这种思维方式才是面试真正考察的东西。5.2 针对滴滴业务特点的额外储备既然你已经准备投滴滴或者类似的出行公司在复习完通用技术栈之外我建议你对出行行业的几个核心业务场景多做了解。这些内容笔试可能不会直接考但在面试中聊到具体项目时能派上大用场。第一个是路径规划与ETA预估。从A点到B点怎么规划最优路线预期到达时间怎么算这背后涉及图论算法、交通流预测、机器学习等。了解一些基本概念比如Dijkstra、A*搜索、ETA回归模型会显得你对业务有热情。第二个是订单匹配与调度。一个订单来了分配给哪个司机这不只是距离最近的问题还要考虑司机当前状态、乘客等待时间、区域供需平衡需要对业务场景有比较全面的认知。第三个是大数据处理。出行平台每天产生海量的轨迹数据、订单数据这些数据怎么存储、怎么计算、怎么发挥价值涉及到Hadoop、Spark、Kafka等大数据技术栈。对分布式系统有一定了解会是你和其他候选人拉开差距的地方。收尾的一点体会把我自己做这套题和准备面试的经验浓缩成一句话笔试考察的不只是你会不会写代码而是你有没有解决问题的完整思路。从算法题里的边界条件到SQL题里的聚合逻辑再到系统设计题里的模块拆分每一个环节都在检验一种工程化思维。很多人刷了一堆题但收效甚微缺的正是这个从“做题”到“解决问题”的转换。我自己在这套题上最大的收获也不是某个具体的算法模板而是养成了一种习惯看到任何题目先拆需求、再定方案、最后写代码一步都跳不得。希望这篇拆解能帮你少走一些弯路把这套题吃透用它校准你自己的复习方向然后在笔试现场稳定发挥。
返回列表