数据来源:真实面经整理 | 版本:final
一、公司画像 & 校招节奏
滴滴是什么样的公司
滴滴出行成立于,总部北京,是全球最大的网约车平台。核心产品覆盖滴滴打车、青桔单车、滴滴货运,以及国际化业务DiDi。截至,年活跃用户超5.7亿,完成订单约174亿次,在职员工约1.5万人。
从技术角度看,滴滴是一家被严重低估的技术公司。C++和Go是双主力语言,这在国内互联网大厂里比较少见——大多数公司要么偏Java,要么偏Go,滴滴同时深度使用两种系统级语言,技术栈有独特性。
滴滴的核心技术壁垒集中在三个方向:
实时调度算法:每天174亿次订单背后,是供需匹配、动态定价、派单优化的实时计算系统。司机和乘客的二分图匹配,要在100ms内完成。这不是普通的业务逻辑,是真正意义上的工程挑战。
地图引擎与路径规划:滴滴自研了部分地图能力,路径规划(Dijkstra、A*)是日常核心需求。地图工程师是滴滴特有的岗位方向,其他大厂几乎没有这个专项。
数据安全合规:下架事件之后,滴滴经历了整整两年的数据安全整改,正式复市。这段经历让滴滴对安全合规的要求非常高,面试中会特别关注候选人的安全意识。
主要招聘方向
| 方向 | 代表业务 | 技术侧重 |
|---|---|---|
| 后端开发(C++) | 调度系统、地图服务 | C++,高并发,实时系统 |
| 后端开发(Go) | 订单服务、用户中台 | Go,微服务,高并发 |
| 算法工程师 | 供需预测、定价算法 | Python/C++,运筹优化 |
| 地图工程师 | 滴滴地图、路径规划 | C++,空间算法,地理信息 |
| 前端/客户端 | App、小程序 | React Native/Swift/Kotlin |
| 数据开发 | 订单分析、用户行为 | Spark/Flink/ClickHouse |
投递建议:C++能力强的同学优先投后端开发(C++)或地图工程师;Go基础扎实的投后端开发(Go);如果两者都会,C++后端竞争会少一些。
校招节奏怎么理解?
| 阶段 | 时间节点 | 关键动作 |
|---|---|---|
| 暑期实习转正 | 实习生转正通道优先开放 | |
| 正式网申 | campus.didichuxing.com 投递 | |
| 笔试 | 编程题3-4道 + 选择题 | |
| 技术面 | 2-3轮技术面 + 1轮HR | |
| Offer发放 | 等待结果 |
一个实用建议:滴滴的暑期实习转正名额有限,但正式校招流程比较完整。如果没有拿到实习转正,正式投递时不要犹豫,滴滴的笔试题难度适中,通过率相对合理。
二、岗位 JD 解析:技术要求拆解
后端开发(C++方向)
拆解JD的核心要求,分成"必须"和"加分"两档:
必须具备: - 扎实的C++基础:内存管理、智能指针、面向对象、模板 - 操作系统:进程/线程/协程,系统调用,内存分布 - 网络编程:TCP/IP,Socket,I/O模型(epoll) - 数据结构与算法:手写常用算法,LeetCode Medium通过率
加分项: - 熟悉Linux环境,会用gdb/valgrind调试 - 了解分布式系统设计(CAP定理、一致性协议) - 有C++大型项目经验(非玩具项目) - 了解路径规划算法(地图工程师必须)
一个容易被忽视的点:滴滴JD里经常出现"高性能系统"四个字。这不是废话,是在暗示面试会重点考系统设计场景题,比如"如何设计一个支持百万并发的派单系统"。提前准备这类题的框架很有必要。
后端开发(Go方向)
必须具备: - 扎实的Go基础:goroutine、channel、interface、内存模型 - 并发编程:sync包、atomic操作、锁的正确使用 - 微服务:gRPC、服务注册发现、熔断降级 - 数据库:MySQL索引优化、Redis使用场景
加分项:
- 熟悉Go的内存逃逸分析,能用go build -gcflags="-m"定位问题
- 了解GMP调度模型的深层原理
- 有高并发Go服务的优化经验
Go方向一个特别提醒:滴滴的Go面试题偏向并发编程的实战,不是背八股文。面试官会给你一个场景,让你现场写goroutine协调代码。这类题必须提前练习,光看不够。
三、LeetCode 高频题 Top 20(真实面经数据)
刷题策略说明
滴滴的算法题整体难度是Medium为主,Hard出现概率低于字节。但有两个特殊点要注意:
- 地图方向有独特考点:Dijkstra最短路径、BFS迷宫遍历是地图工程师必考内容,普通后端岗不考
- Go方向有并发编程代码题:不是纯粹的LeetCode题,是goroutine协调场景,需要单独准备
以下Top 20来自真实面经整理,按重要程度分梯队:
第一梯队:必刷(基础入场券)
| # | 题目 | 核心考点 | 备注 |
|---|---|---|---|
| 1 | No.206 反转链表 | 链表基础 | 入场券,不会直接挂 |
| 2 | No.146 LRU缓存机制 | 哈希表+双向链表 | 高频,会结合缓存设计考 |
| 3 | No.102 二叉树层序遍历 | BFS | 地图路径规划的基础 |
| 4 | 手撕快速排序 | 递归+分治 | 滴滴考手撕,不能只背思路 |
| 5 | Dijkstra最短路径 | 图算法 | 地图方向必考,后端可选 |
No.146 LRU为什么高频:滴滴面试系统设计时经常问"如何缓存热点司机信息",LRU是最自然的答案。面试官会从这道题延伸到Redis缓存设计,一题多用。
第二梯队:高频(重点准备)
| # | 题目 | 核心考点 |
|---|---|---|
| 6 | No.215 数组中的第K大元素 | 堆/快速选择 |
| 7 | No.15 三数之和 | 双指针 |
| 8 | No.141 环形链表 | 快慢指针 |
| 9 | No.236 二叉树最近公共祖先 | 递归 |
| 10 | No.21 合并两个有序链表 | 链表操作 |
| 11 | No.3 无重复字符的最长子串 | 滑动窗口 |
| 12 | No.56 合并区间 | 排序+贪心 |
| 13 | No.42 接雨水 | 双指针/单调栈 |
| 14 | No.200 岛屿数量 | BFS/DFS |
| 15 | No.239 滑动窗口最大值 | 单调队列 |
第三梯队:中频(时间够再刷)
| # | 题目 | 核心考点 |
|---|---|---|
| 16 | No.25 K个一组翻转链表 | 链表 |
| 17 | No.5 最长回文子串 | 动态规划 |
| 18 | No.46 全排列 | 回溯 |
| 19 | No.322 零钱兑换 | 动态规划 |
| 20 | No.72 编辑距离 | 动态规划 |
滴滴特有的并发编程代码题
这不是LeetCode题,但在Go方向面试中真实出现过:
题目:用N个goroutine,每个goroutine负责输出一个数字,按升序协调输出1到N。
核心思路:用channel传递令牌,每个goroutine只有收到令牌才能输出,输出完传给下一个。
// 3个goroutine协调输出1,2,3的核心逻辑
func main() {
n := 3
channels := make([]chan struct{}, n)
for i := range channels {
channels[i] = make(chan struct{}, 1)
}
for i := 0; i < n; i++ {
go func(id int) {
<-channels[id] // 等待令牌
fmt.Println(id + 1) // 输出自己的数字
if id+1 < n {
channels[id+1] <- struct{}{} // 传给下一个
}
}(i)
}
channels[0] <- struct{}{} // 启动第一个
time.Sleep(time.Second)
}
这道题考的不是算法,是对channel通信模型的理解,必须能手写出来。
四、技术面试考点
C++ 专项(C++后端,权重 ⭐⭐⭐⭐⭐)
滴滴特色考点一:友元函数和友元类
这是从真实面经里提炼出来的滴滴特色题,其他大厂问得少,滴滴频繁出现。
友元函数的核心:
- 不是类的成员函数,但可以访问类的所有私有成员
- 最常见用途:实现operator<<运算符重载,需要访问私有数据
- 语法:在类内用friend关键字声明
友元类:整个类可以访问另一个类的私有成员,相当于"批发"了友元权限。
两个必须记住的特性: - 友元关系不能继承:父类的友元不是子类的友元 - 友元关系不能传递:A是B的友元,B是C的友元,A不是C的友元
追问:为什么友元破坏封装性?因为它让外部代码可以直接操作私有成员,绕过了对外接口,破坏了"通过接口访问"的封装原则。
滴滴特色考点二:系统调用与线程切换
这道题考的是操作系统基础,但角度比较刁钻,面试官会连环追问:
-
系统调用能否引起线程切换?→ 可以。当系统调用阻塞时(比如read等待I/O),OS会将当前线程挂起,切换到就绪队列中的其他线程。非阻塞系统调用通常不会触发切换。 -
malloc是系统调用吗?→ 不是。malloc是C标准库(glibc)的函数,在用户态执行。它底层会调用brk()(扩展堆空间)或mmap()(申请匿名内存映射),这两个才是真正的系统调用。 -
brk和mmap的区别?→ brk扩展堆的末端,适合小内存分配(<128KB);mmap直接向OS申请新的内存映射,适合大块内存分配,free之后可以直接归还OS。
智能指针三件套:
- unique_ptr:独占所有权,不可拷贝,只能move转移
- shared_ptr:共享所有权,引用计数,计数归零自动释放
- weak_ptr:弱引用,不增加引用计数,用于打破循环引用
Go 语言专项(Go后端,权重 ⭐⭐⭐⭐⭐)
滴滴特色考点一:Go map并发安全
直接问:多个goroutine同时读写map会怎样?
答:程序会panic: concurrent map read and write,Go的map不是线程安全的,并发读写会触发运行时panic。
三种解决方案:
| 方案 | 适用场景 | 原理 |
|---|---|---|
| sync.Mutex | 读写频率相近 | 全局加锁,简单粗暴 |
| sync.RWMutex | 读多写少 | 读可并发,写独占 |
| sync.Map | 读多写少,key稳定 | 双层结构,读操作无锁 |
sync.Map的内部结构:read(atomic存储,读操作无锁)+ dirty(加锁写入)双层设计。读请求先访问read,命中则直接返回;miss达到阈值后,将dirty提升为read。
滴滴特色考点二:Channel 6种典型场景
面试官不会让你背八股,会问"你在什么场景下用channel"。要能举出具体例子:
- 生产者-消费者:用单向channel传递数据,生产者
chan<- T,消费者<-chan T - 超时控制:
select + time.After(timeout),避免goroutine永久阻塞 - 信号量(限流):带缓冲channel,
make(chan struct{}, N)限制最大并发数 - 广播通知:
close(ch)关闭channel,所有接收方都会收到零值,实现一对多通知 - Pipeline:多个goroutine通过channel串联成流水线,每个处理一个阶段
- goroutine协调升序输出:即上面的代码题,用channel传递"执行令牌"
GMP调度模型简版:G(goroutine)、M(系统线程)、P(逻辑处理器)。P的数量由GOMAXPROCS决定,默认等于CPU核数。G挂在P的本地队列,M绑定P执行G。当G阻塞时,M会解绑P,让其他M使用P继续执行其他G。
实时调度系统(滴滴独特考点,权重 ⭐⭐⭐⭐⭐)
这是滴滴跟其他大厂最不一样的地方。面试系统设计题,几乎一定会绑定出行业务场景。
派单系统设计: - 核心问题:如何在100ms内完成司机和乘客的最优匹配? - 简化版回答:将司机和乘客建模为二分图,用匈牙利算法或贪心策略求最大匹配 - 实时性保障:预计算附近司机的候选集(用Redis GEO),减少实时计算量 - 热点分片:同一区域大量请求集中时,按网格分片处理,避免单点成为瓶颈
路径规划: - Dijkstra:适合静态路网,找单源最短路径 - A*:在Dijkstra基础上加启发式函数,更快找到目标 - 实际应用:会考虑路况(实时权重更新)、道路限制(单行道、禁行)
Redis 专项(权重 ⭐⭐⭐⭐)
缓存三问:穿透/击穿/雪崩,滴滴特别关注,必须背全。
- 缓存穿透:查询不存在的key,每次都打到数据库。解决:布隆过滤器前置拦截,或缓存空值。
- 缓存击穿:热点key过期,大量请求同时打到数据库。解决:互斥锁(只有一个请求重建缓存)、永不过期(逻辑过期时间)。
- 缓存雪崩:大量key同时过期,数据库压力骤增。解决:随机TTL偏移、缓存预热、熔断降级。
Redis GEO命令(滴滴特有考点):
- GEOADD:添加地理坐标(附近司机上线)
- GEORADIUS:查询指定半径内的成员(查找5km内的空闲司机)
- 底层实现:将经纬度编码为52位GeoHash字符串,存储在ZSet中
ZSet做司机评分排行榜:ZADD driver:score 4.9 driver_001,ZREVRANGE按分数倒序查询。
数据库(权重 ⭐⭐⭐⭐)
分库分表(出行场景必考): - 订单表分片策略:按城市分库(北京/上海/...),每个城市再按时间分表(按月) - 查询挑战:跨城市查询、历史数据查询需要走离线数仓,不走在线MySQL
MVCC简版:MySQL InnoDB通过版本链(undo log)和Read View实现多版本并发控制,读操作不加锁,通过"快照读"看到一致的数据视图。
五、面经规律总结
面试整体风格
从大量面经里归纳出三个关键词:实战、底层、场景化。
滴滴的面试官倾向于问"你怎么解决XXX问题",而不是"说一下XXX的定义"。即使是基础知识,也会用业务场景来包装。
比如问Redis,不会直接问"什么是缓存雪崩",而是"滴滴节假日打车高峰期,大量司机位置数据缓存同时过期,你怎么设计"——本质还是缓存雪崩,但你必须在业务语境下回答。
高概率追问链
C++方向:
-
友元函数能做什么? → 友元关系能继承吗?(不能) → 为什么友元破坏封装性?(绕过接口直接访问私有成员)
-
系统调用会引起线程切换吗? → malloc是系统调用吗?(不是,是库函数) → malloc底层调用什么?(brk / mmap) → brk和mmap的区别?
-
shared_ptr怎么避免内存泄漏? → 什么情况下会循环引用? → weak_ptr怎么打破循环引用?
Go方向:
-
Go map是线程安全的吗? → 并发读写会怎样?(panic) → 怎么解决?(sync.Map / sync.Mutex) → sync.Map内部结构是什么?(read + dirty双层) → 读多写少为什么用sync.Map更好?
-
channel的用途有哪些? → channel底层数据结构是什么?(环形缓冲区 + 发送/接收goroutine队列) → 向已关闭的channel发送会怎样?(panic) → 从已关闭channel接收会怎样?(返回零值 + false)
Redis方向:
- Redis缓存雪崩怎么解决? → 随机TTL为什么能减轻雪崩?(过期时间打散,避免同时失效) → 缓存预热怎么做?(系统启动时主动加载热点数据) → 如果Redis集群也挂了呢?(熔断降级,降级到DB限流查询)
笔试特点
- 题型:编程题3-4道 + 选择题(C++/Go语法、OS、计算机网络)
- 难度:Easy×1 → Medium×2-3,Hard极少出现
- 时间:90-
- 特别注意:选择题里可能出现C++代码题,给一段代码问"输出是什么"或"哪里有错误"——这考的是对C++内存模型、构造/析构顺序的理解,不是算法题,要单独准备
面试节奏
一般是2-3轮技术面 + 1轮HR。
- 一面:算法题 + C++/Go基础 + 项目介绍
- 二面:系统设计(几乎必出派单/调度场景) + 深度技术问题
- 三面(如有):高级工程师或TL,更注重架构思维和工程判断
- HR面:职业规划、稳定性、薪资期望
一个需要特别准备的点:项目中与实时性相关的内容。滴滴对延迟敏感,面试官很可能会问"你项目里最低的P99延迟是多少"、"你们怎么保证接口响应时间"。如果你的项目有性能优化经历,一定要梳理清楚数据。
校招节奏
总体策略
滴滴备考的核心矛盾是:语言深度 vs 系统设计广度。
C++后端方向,语言底层要理解得够深;Go方向,并发编程要能手写。系统设计题,出行场景必须提前准备专项框架。的分配建议把前2/3时间给技术深度,后1/3给系统设计和冲刺。
详细计划
| 阶段 | 时间 | 重点任务 | 验收标准 |
|---|---|---|---|
| C++ 底层专项 | 友元函数/系统调用/智能指针/STL底层实现 | 能解释友元不能继承的原因;malloc不是系统调用能说清楚 | |
| Go 并发专项 | GMP模型/Channel 6种场景/sync.Map/内存逃逸分析 | goroutine升序输出代码题能手写;sync.Map双层结构能解释 | |
| 数据库 + Redis | 缓存三问/Redis GEO命令/MySQL分库分表/MVCC | 三问的解决方案各能给出2-3种;GEO命令使用场景能举例 | |
| 实时系统设计 | 派单系统设计/路径规划算法/热点分片处理 | 设计一个100ms内响应的派单系统框架能说清楚 | |
| 算法专项 | Dijkstra/LRU/链表全系列/滑动窗口 | Top 20中第一、二梯队题目能独立AC | |
| 冲刺 | 看滴滴真实面经/整理项目实时性数据/模拟面试 | 完成2次以上完整模拟面试 |
最低备考标准 Checklist
上述走完之后,用这个清单做最终检验:
- [ ] C++友元函数的作用和限制能清楚解释(友元不能继承,破坏封装性)
- [ ] malloc不是系统调用、底层是brk/mmap这个区别能说清楚
- [ ] Redis缓存雪崩的3种以上预防方案能给出
- [ ] Go goroutine并发读写map的问题和sync.Map的解决方案能讲清楚
- [ ] goroutine按升序协调输出(N个goroutine传递令牌)的代码逻辑能手写
- [ ] 设计派单系统的基本框架能说出来(二分图匹配 + Redis GEO + 热点分片)
- [ ] Dijkstra算法能手写(地图方向必须,后端方向加分)
- [ ] LRU缓存(No.146)能独立手写
全部通过,你已经具备参加滴滴技术面的基础条件。
给不同背景同学的建议
只会Java的同学:如果确定要投滴滴后端,必须在备考前补C++或Go的基础。滴滴C++/Go方向对Java几乎没有需求,硬投Java后端大概率简历就过不了。
C++扎实但没用过Go的同学:优先投C++后端,不要同时准备两个语言。Go可以在面试结束后慢慢学。
既会C++又会Go的同学:把两个方向都投了,滴滴有双语言方向,这是优势,要充分利用。
目标地图工程师的同学:Dijkstra和A*算法必须手写熟练,空间数据结构(R-Tree、KD-Tree)了解一下,GIS基础如果有更好。