数据来源:真实面经整理 | 版本:final
一、公司画像 & 校招节奏
Momenta是什么公司?
Momenta成立于,总部在北京,是国内自动驾驶赛道的头部玩家之一。创始团队来自微软亚研院、商汤等顶尖机构,核心竞争力不是堆硬件,而是数据飞轮。
什么是数据飞轮?简单说:量产车收集路测数据 → 数据喂给感知算法 → 算法迭代更强 → 更强的算法装进量产车 → 再收集更多数据。这个闭环转起来,竞争壁垒就越来越高。
核心产品两条线: - Mpilot:量产辅助驾驶系统,已经规模化前装上车,合作车企包括上汽、吉利等 - MSD(Momenta Self-Driving):下一代高级自动驾驶系统,面向更高阶的L4目标
从工程视角看,Momenta的技术栈很有特色: - 感知算法层:Python + PyTorch 训练,C++ 推理部署 - 系统层:C++ 为绝对主力(实时性要求高) - 数据平台层:Go 语言(高并发数据处理) - 工具链:CUDA/TensorRT(模型加速)
校招节奏
Momenta规模相对大厂小一些,但校招节奏比较规律:
| 批次 | 时间 | 说明 |
|---|---|---|
| 实习招募 | 每年2- | 优先转正,是进Momenta的最优路径 |
| 秋招正式批 | 8- | HC有限,竞争激烈 |
| 春招补充 | 次年3- | 补充少量HC,机会少 |
关键建议:如果目标是Momenta,强烈建议走实习转正路径,转正率明显高于社招。秋招的HC每年约100-200人,自动驾驶赛道整体HC比互联网少,要早准备。
二、岗位JD解析:技术要求拆解
Momenta校招主要招以下几类岗位:
感知算法工程师(最热门)
核心要求: - 扎实的深度学习基础(CNN/Transformer架构) - 熟悉目标检测/语义分割方向(YOLO系列、BEV感知是加分项) - C++ 推理代码要会写,不只是会调Python API - 了解模型压缩/量化/TensorRT加速
隐性要求(JD没写但面试必考): - 数据增强策略(不只是知道有哪些,要能说清楚为什么用) - 了解Momenta飞轮模型的数据闭环逻辑 - BEV(Bird's Eye View)感知是以后的热点,熟悉BEVFusion/BEVFormer加分
自动驾驶系统工程师
核心要求: - C++ 功底要扎实,不是普通的"会用",是系统级的用 - 进程间通信(IPC)、内存管理、性能优化 - 实时系统开发经验(嵌入式/车载平台) - 了解ROS或自研消息中间件
面试必考:共享内存、多进程通信、C++性能优化(这是Momenta系统岗的特色考点)
后端/数据工程师
核心要求: - Go 语言熟练(不是了解,是熟练) - 分布式系统基础(数据飞轮平台本质是分布式数据处理系统) - Kafka/消息队列使用经验 - 数据库(MySQL/Redis)
面试必考:Go的并发模型(goroutine/channel)、map的线程安全问题、Go map扩容机制
三、LeetCode高频题Top 20(真实面经数据)
Momenta算法面试整体在中等难度,不追求极难题,但要求代码质量高(不只是思路对,要写出可以上生产的代码)。C++方向用C++写,Go方向用Go写。
必刷题目(出现频率极高)
1. 反转链表(No.206)
基础中的基础,几乎必考。C++要能写出迭代和递归两种版本,面试官会追问时间复杂度和空间复杂度的区别。
2. 环形链表II(No.142)
快慢指针找环入口。不只是判断有没有环,要找到入口节点。这道题考察数学推导能力,能说清楚为什么两指针相遇点到入口距离等于头节点到入口距离是加分项。
3. 最大子数组和(No.53)
Kadane算法,DP的入门题。系统工程师也会被考到。要能从暴力解法讲到O(n)优化,展示思维过程。
4. 二叉树层序遍历(No.102)
BFS标准题型,队列实现。变体很多,要能举一反三(锯齿形遍历、求最大宽度等)。
5. 合并K个有序链表(No.23)
优先队列(小顶堆)解法,也可以用分治。面试官会问两种方法的时间复杂度对比,K个链表总共N个节点,堆解法是O(N log K)。
高频题目(至少掌握思路)
6. 手写快速排序
这是Momenta系统岗必考的手写题。要能写出标准分区版本,讨论最坏情况和随机化优化。C++实现细节要注意:partition的边界处理。
7. 最长公共子序列(No.1143)
经典二维DP。Momenta数据工程方向会考,因为序列对比问题在数据处理场景有实际应用。
8. 课程表(No.207)
拓扑排序,检测DAG(有向无环图)中是否有环。自动驾驶的任务调度模块本质上就是DAG,面试官有时候会把这道题和实际场景结合来问。
9. 滑动窗口最大值(No.239)
单调队列(deque)维护窗口最大值,O(n)解法。考察候选人对数据结构的灵活使用。
10. 二叉树最近公共祖先(No.236)
后序递归经典题。要能写出通用版(非BST情况),并清楚说明递归逻辑。
中频题目(有一定出现概率)
- 删除链表的倒数第N个节点(No.19)- 双指针
- 字符串转整数 atoi(No.8)- 边界条件处理,系统岗必考
- 最长无重复子串(No.3)- 滑动窗口
- 买卖股票的最佳时机(No.121)- 贪心/DP
- 岛屿数量(No.200)- DFS/BFS
- 全排列(No.46)- 回溯
- 二叉搜索树中序遍历(No.94)- 递归/迭代
- 接雨水(No.42)- 双指针或单调栈
- 最小栈(No.155)- 数据结构设计
- 有效括号(No.20)- 栈的应用
四、技术面试考点
Momenta面试有几个特色考点,跟普通互联网公司不太一样,重点说。
C++ 系统级考点
1. 共享内存用法及场景
这是Momenta系统岗高频考点,原因是自动驾驶系统中多个进程(感知、规划、控制)需要高速交换数据。
共享内存是Linux IPC(进程间通信)机制之一,核心API:
// 创建/获取共享内存
int shmid = shmget(key, size, IPC_CREAT | 0666);
// 挂载到当前进程地址空间
void* ptr = shmat(shmid, nullptr, 0);
// 用完后解除挂载
shmdt(ptr);
// 删除共享内存
shmctl(shmid, IPC_RMID, nullptr);
为什么比Socket快? Socket要经过内核态/用户态的数据拷贝(至少2次),共享内存是两个进程直接映射同一块物理内存,零拷贝。大数据量(比如点云/图像帧)的传输优势非常明显。
缺点是什么? 共享内存本身没有同步机制,多进程同时读写会出问题,需要配合信号量(semaphore)或互斥锁(mutex)使用。
面试会追问:如果感知进程写数据,规划进程同时在读,怎么保证一致性?答案是用读写锁(pthread_rwlock)或者基于版本号的无锁读写。
2. vector 大规模数据优化
自动驾驶系统里vector用得非常多(点云数据就是vector<Point3D>),优化是真实工程问题。
优化方向1:预分配
// 反例:不知道大小,让vector自动扩容
std::vector<PointCloud> data;
for (auto& frame : frames) {
data.push_back(frame); // 可能触发多次扩容
}
// 正例:如果知道大小,提前reserve
data.reserve(expected_size);
优化方向2:用emplace_back替代push_back
// push_back:先构造临时对象,再拷贝/移动进vector
data.push_back(PointCloud(args...));
// emplace_back:直接在vector内部原地构造
data.emplace_back(args...); // 减少一次构造
优化方向3:移动语义
当vector存的是大对象,用std::move避免深拷贝:
std::vector<LargeObject> target;
target.push_back(std::move(source_obj)); // 而不是拷贝
3. vector vs array 的本质区别
| 对比维度 | std::array | std::vector |
|---|---|---|
| 内存位置 | 栈(stack) | 堆(heap) |
| 大小 | 编译期固定 | 运行期动态 |
| 运行时开销 | 几乎零开销 | capacity管理开销 |
| 越界检查 | 无(at()除外) | 无(at()除外) |
| 适用场景 | 小固定大小 | 大或不确定大小 |
面试官常问:什么时候用array更好?答:大小编译期可知且不大(比如矩阵4x4),放栈上避免堆分配开销,对实时性要求高的系统(如车载ECU)很重要。
Go 语言专项考点(后端/数据方向)
4. Go 线程安全数据类型
Go原生线程安全的机制:
- sync.Mutex / sync.RWMutex:互斥锁,手动加锁
- sync.Map:并发安全的map,适合读多写少场景
- channel:Go的核心并发原语,通过通信来共享内存
- sync/atomic包:原子操作,适合简单计数器
不是线程安全的:
- 原生map:并发读写会panic(Go 1.6后会检测并panic)
// 错误示范:多个goroutine并发写同一个map
m := make(map[string]int)
go func() { m["key"] = 1 }() // 并发写,会panic
go func() { m["key"] = 2 }()
// 正确做法1:sync.Mutex
var mu sync.Mutex
mu.Lock()
m["key"] = 1
mu.Unlock()
// 正确做法2:sync.Map(适合读多写少)
var sm sync.Map
sm.Store("key", 1)
val, ok := sm.Load("key")
5. Go map 不可寻址问题
这是Momenta Go岗真实考点,很多候选人第一次遇到会蒙。
type Point struct {
X, Y int
}
m := map[string]Point{"a": {1, 2}}
// 错误:不能这样修改!
m["a"].X = 10 // 编译报错:cannot assign to m["a"].X
// 为什么?map的value不可寻址(cannot take address of map value)
// Go规范:map的value在内存中可能会因为扩容而移动,
// 所以不允许直接取地址
解决方案:
// 方案1:取出来,改了,放回去
p := m["a"]
p.X = 10
m["a"] = p
// 方案2:value改成指针类型
m2 := map[string]*Point{"a": {1, 2}}
m2["a"].X = 10 // OK,指针可以寻址
6. Go map 两种扩容方式
这是Momenta Go岗最高频的深度考点,要说清楚两种扩容触发条件和目的。
方式1:翻倍扩容(增量扩容) - 触发条件:装载因子 > 6.5(即平均每个bucket超过6.5个key) - 操作:bucket数量翻倍,逐步迁移数据(渐进式迁移,不会一次性全部迁移,避免阻塞) - 目的:解决数据过多导致的查找性能下降
方式2:等量扩容(等量整理) - 触发条件:overflow bucket(溢出桶)数量过多,超过正常bucket的数量 - 操作:bucket数量不变,重新整理,把溢出桶的数据迁回正常桶 - 目的:解决大量删除操作后产生的内存碎片问题
面试追问:为什么要渐进式迁移而不是一次性迁移?因为Go的map操作要保证低延迟,一次性迁移大量数据会阻塞整个goroutine,渐进式迁移把开销分散到后续的每次读写操作中。
感知算法考点(算法岗)
感知算法岗的技术面考察分两层:
基础层(每个候选人都要过): - 卷积神经网络基础(感受野、BN层、残差连接为什么有效) - 目标检测框架(YOLO系列的演进:从YOLOv1到YOLOv8,说清楚主要改进点) - 损失函数(分类用CE,回归用Smooth L1,IoU Loss的变体) - 数据增强策略(为什么用,怎么选,对不同任务的影响)
进阶层(有相关经历的候选人): - BEV(鸟瞰视角)感知:将多个相机/激光雷达的数据统一到俯视角坐标系 - BEVFusion:相机+激光雷达融合的代表性工作 - 模型压缩:剪枝、量化(INT8量化的原理和精度损失权衡)、知识蒸馏 - TensorRT加速:算子融合、精度校准
五、面经规律总结
整理Momenta历届面经,有几个规律值得注意:
面试流程
一般是4-5轮: 1. HR初筛(15-):了解背景、实习经历、期望方向 2. 技术一面(60-):算法题1-2道 + 基础知识考察 3. 技术二面(60-):深度技术考察 + 项目细问 4. 技术三面(主管面,45-):项目思路 + 综合判断 5. HR终面():薪资、入职时间等
特色考察方式
追问式深挖:Momenta面试官喜欢从一个问题层层追问。比如问你用过vector,下一句是"有没有遇到性能问题",再下一句是"怎么优化的",再下一句是"为什么这样优化而不是换数据结构"。准备时要建立知识体系,不只是记答案。
结合项目经历:纯背八股文在Momenta不太好使,面试官会把技术问题和你的项目联系起来。你说了解共享内存,他会问"你在哪个项目里用过,解决了什么问题"。准备2-3个项目经历,能结合技术点讲清楚。
代码质量要求高:手写代码不只是思路对,要考虑边界条件(null指针、空数组、负数输入),命名规范,注释。自动驾驶公司对代码质量非常在意,因为车载软件的质量直接和安全性挂钩。
常见失误
- Go map线程安全问题:很多候选人说"map不是线程安全的"但说不清楚为什么,也不知道解决方案,直接扣分
- C++只会用不会优化:说会C++但从没考虑过vector扩容的开销,在系统岗会减分
- 对飞轮模型没概念:Momenta非常看重候选人是否了解公司的核心技术路线,面试前务必研究一下飞轮模型
校招节奏
面向Momenta后端/系统方向(C++/Go):
第一周:C++ 深度专项()
| 天 | 任务 |
|---|---|
| 内存管理:堆/栈/智能指针(unique_ptr/shared_ptr/weak_ptr),写代码实际跑,不只是背 | |
| 进程间通信:共享内存(shmget/shmat)+ 信号量同步,写一个简单的多进程demo | |
| STL深度:vector扩容机制/emplace_back/移动语义,对比array和vector的使用场景 | |
| C++复习:对照Momenta面经,把高频考点过一遍,查漏补缺 |
第二周:算法专项()
| 天 | 任务 |
|---|---|
| 链表专项:反转链表、环形链表II、删除倒数第N个节点、合并K个有序链表 | |
| 二叉树专项:层序遍历、最近公共祖先、二叉搜索树相关 | |
| 动态规划:最大子数组和、最长公共子序列、买卖股票系列 | |
| 综合练习:手写快排 + 图论(课程表/拓扑排序) |
第三周:Go 语言专项()
| 天 | 任务 |
|---|---|
| Go并发基础:goroutine / channel / select,写真实并发程序跑一下 | |
| Go map深度:底层结构(bucket/overflow bucket)、扩容机制、线程安全问题 | |
| sync包全家桶:Mutex/RWMutex/WaitGroup/sync.Map,对比使用场景 | |
| Go项目复盘:用Go写过的项目,梳理出能结合上述知识点讲的经历 |
第四周:自动驾驶基础 + 收尾()
| 天 | 任务 |
|---|---|
| 自动驾驶基础:感知(检测/分割)→ 预测 → 规划 → 控制,理解各模块分工 | |
| BEV感知入门:为什么要转换到BEV视角,BEVFusion的核心思路 | |
| 数据飞轮模型:认真研究Momenta官方技术博客,理解飞轮模型的技术实现路径 | |
| 系统设计:设计一个数据处理pipeline(数据采集→清洗→标注→训练→部署) | |
| 模拟面试:找同学互相模拟,重点练追问式对话,准备好3个项目经历的故事线 |
额外建议
实习比秋招重要:如果你是大三或研一,现在就可以投Momenta实习。实习3个月转正成功率远高于秋招,而且能真正感受公司文化和技术氛围,确认是否适合自己。
关注技术博客:Momenta有对外发布技术分享,跟着看能了解公司真实的技术挑战。面试时能结合公司技术方向谈自己的理解,会让面试官刮目相看。
C++和Go不需要都精:系统岗专注C++,数据/后端岗专注Go,算法岗专注Python+C++。不要贪多,深度比广度更重要。
写在最后:自动驾驶是一个工程复杂度极高的领域,Momenta的面试本质上在筛选能在高复杂度系统下写出可靠代码的工程师。八股文只是入场券,真正拉开差距的是项目经历和系统思维。备考时不只是刷题背题,多想想"这个知识点在实际系统里会怎么用",这才是Momenta想要的候选人。