自动驾驶算法岗笔试全解析:从LeetCode到C++工程能力

发布时间:2026/9/1 21:21:31
自动驾驶算法岗笔试全解析:从LeetCode到C++工程能力 1. 从“笔试卷一”拆出来的能力模型1.1 为什么这份卷子值得反复研究2020年校招季我点开图森未来笔试链接的时候心里其实没底。两个小时的答题时间界面简洁得有点冷淡顶部挂着“图森未来2020校招笔试卷一”几个字。那时候我对自动驾驶公司的笔试还停留在“多刷LeetCode就够”的认知里结果真正做到后面才发现光会刷题远远不够。后来我复盘了很久也和当年一起投递的同学对过题才慢慢看懂这份卷子的用意。它几乎把自动驾驶算法岗需要的基本功全摊开了编程、数学、机器学习理论、C工程素养不是面面俱到地堆题目而是每一样都真刀真枪地考点到即止但又直戳要害。这篇文章不会把原题一字不差地搬出来而是基于当年考完后的复盘和多位同学的反馈把这份卷子背后的考察逻辑完整拆开。准备自动驾驶算法岗校招、实习或者单纯想看看工业界笔面试和学校考试有什么区别的同学都可以按下面的思路顺一遍。1.2 自动驾驶公司的第一轮筛人逻辑校招简历量太大了。图森这类自动驾驶公司算法岗投递量通常上千技术面试官的时间非常有限笔试就成了第一道漏斗。笔试不追求把你考倒而是用最短的时间判断三类能力基础是否扎实能不能不看库函数手写一个不超时的算法能不能把链式求导、贝叶斯公式推到正确。工程习惯是否到位写的代码是不是能跑、可读、边界处理干净C资源管理有没有意识。遇到没见过的问题时的思路很多题包装成工程场景传感器合并、碰撞检测、坐标系变换实际考点依然是经典算法和数据结构的变体。这里有个细节值得注意卷子名字写着“一”意味着它不是只有一套卷。校招笔试有时候是系统随机抽题有时候是分卷考查。一般“一”会更偏通用基础和综合能力“二”可能针对具体方向或加大难度。所以不要以为这一套考得好就万事大吉准备时要按整个流程来做。从公司角度想自动驾驶卡车要面对的是真实道路上的长距离运输传感器数据量巨大实时性要求极高。团队需要的不是只会调库的人而是能理解模型底层原理、还能把代码稳稳落到车里的工程师。笔试里的算法题、概率题、C题本质都是这个能力模型的投影。2. 题型结构与考察重心不止是LeetCode2.1 编程题手撕代码只是入场券从题目占比来看编程题大概能占到总分的45%到55%一般是2到3道。按我自己刷题的经验这部分难度是按梯度排列的第一道偏热身链表、数组操作或者简单双指针考察基本语法和代码手感第二道进入常见算法二分查找、DFS/BFS、动态规划都有可能第三道会带有工程包装比如“合并多个传感器数据区间”“多路归并时间戳数据”表面看是业务场景剥掉壳以后就是经典题目。说到区间合并我觉得这件事特别能体现“为什么自动驾驶公司爱考这类题”。一辆卡车上有摄像头、激光雷达、毫米波雷达、GPS、IMU它们以不同频率采集数据要融合成一个全局时间线就得把时间段对齐、合并重叠区间。笔试里考“合并区间”并不是故意拿LeetCode原题凑数而是这个操作在真实系统里天天用得上。编程题的评分也不是只看最终能不能跑通。考官会看代码风格、变量命名、边界条件处理、时间空间复杂度。有人在笔试里用了一个O(n²)的双重循环处理10^6的数据样例过了但后台用大数据一测直接超时这种教训在后续章节里我会细说。2.2 数学与概率题模型怎么推的这里就怎么答数学和概率题大约占25%到30%常见考法分两种。一种是选择或填空专考定义和概念比如协方差、期望、贝叶斯公式、最大似然估计。另一种是简答或推导题让你手写完整的推导过程。卡尔曼滤波的预测更新、高斯分布的乘积归一化、逻辑回归的梯度推导这几类都属于高频考点。这些内容听起来像学校考卷但在自动驾驶里全是日常。感知模块要对目标状态做估计定位模块要把GPS和IMU的数据融合控制模块要预测车辆下一时刻的位置这些底层算法都是概率和线性代数的组合。笔试这一关不考具体的车型或传感器型号而是考模型里的数学机制能不能推明白。这里我想专门提醒一句关键是过程不只是结果。有的同学写得很快直接给最终公式评卷人根本看不出你是背下来的还是真的会推分数就可能被打折。要像写论文附录一样分步骤写清楚目标函数是什么、怎么求导、令梯度为零还是走梯度下降、最后怎么整理成标准形式。哪怕某一步算错了只要思路在还能拿过程分。2.3 机器学习与深度学习基础概念题背后的理解深度这部分占15%左右但含金量不低。常见问题包括什么是过拟合怎么解决L1和L2正则化的区别Dropout在训练和推理时有什么区别BatchNorm的原理反向传播的链式法则手算不同优化器SGD、Momentum、Adam的本质差异。很多人容易把这些题当作“背诵题”背几个要点就上。但图森这种自动驾驶公司模型最终要在嵌入式平台上跑对占用、延迟、泛化能力都非常敏感。笔试里问正则化可能后续面试就会追问“L2正则化为什么等价于权重衰减”“Dropout为什么能看成集成学习”。笔试阶段把概念理解到位了后续面试才不至于露馅。我建议复习时不要只看结论把每个概念用“是什么、为什么、怎么用、有什么代价”四段式过一遍。比如L1正则化为什么能把权重推向稀疏因为它对应拉普拉斯先验在零点附近有尖峰L2对应高斯先验让权重整体变小但不强制为零。这种理解深度笔试题一考一个准。2.4 C工程题不考语言的自动驾驶公司是少数图森未来2020校招笔试卷一里C题目基本集中在RAII、智能指针、内存管理、构造函数和析构函数的调用顺序偶尔还会考标准库容器的时间复杂度。这个问题初看很“语言细节”但往深了想就明白为什么重要自动驾驶系统对实时性和稳定性要求极高C写不好内存泄漏、悬垂指针、未定义行为放到实车环境里就是事故隐患。笔试里考智能指针不是考你能不能默写代码而是看你能不能讲清楚资源所有权转移的逻辑。比如unique_ptr为什么不能拷贝、只能移动shared_ptr的引用计数在多线程下怎么做原子操作weak_ptr怎么打破循环引用。这些不是孤立的记忆点而是C资源管理的顶层设计。把整体配比整理成一张表方便对照检查题型大概占比核心考察点建议用时编程题45%-55%算法、数据结构、代码规范、边界处理60-70分钟数学/概率推导25%-30%概率基础、最优化、模型推导30-35分钟机器学习/深度学习基础15%过拟合、反向传播、优化器、网络结构15-20分钟C工程素养10%-15%内存、RAII、容器、编译链接10-15分钟这个配比不是一个官方数据是结合同类岗位笔试复盘出来的经验值但趋势很一致算法永远是重头数学与模型不能丢工程能力是底线也是加分项。3. 高频考点的解题思路与代码示范3.1 区间合并从LeetCode变形到多传感器数据同步有一道题我认为大概率出现在这类卷子里就是区间合并。原版是LeetCode 56但笔试卷里常常会加约束区间数量n最大10^6每个区间的起止值可能超过int范围。真正做题的时候这些约束比题目本身更值得注意。解题思路很固定先按起点排序再线性扫描维护当前合并区间的右端点。如果下一段区间的起点小于等于当前右端点说明重叠更新右端点为两者的较大值否则把当前合并段收进结果然后开启新的一段。排序是O(nlogn)扫描是O(n)整体跑大数据没有压力。#include vector #include algorithm using namespace std; vectorpairlong long, long long mergeIntervals( vectorpairlong long, long long intervals) { if (intervals.empty()) return {}; sort(intervals.begin(), intervals.end()); vectorpairlong long, long long ans; ans.push_back(intervals[0]); for (size_t i 1; i intervals.size(); i) { auto last ans.back(); if (intervals[i].first last.second) { last.second max(last.second, intervals[i].second); } else { ans.push_back(intervals[i]); } } return ans; }这里我用long long是因为题目如果涉及大范围时间戳int可能溢出这是笔试里非常容易踩的隐藏坑。另外要强调一点不要在循环里反复调用sort或者反复插入开头复杂度会退化。区间合并的套路背下来不难难的是知道什么时候用sort、什么时候用差分数组、什么时候用扫描线这需要看到题目条件再决定。我之前还见过一道变形题给定一堆有序的传感器时间片段每个片段带权重找出被最多时间段覆盖的时间点。这就是典型的差分数组加扫描线复杂度做到O(nlogn)。如果你只会区间排序合并碰到这种题会卡住。所以复习的时候区间相关的三类套路都要过一遍合并区间、区间交集、最大重叠点。3.2 贝叶斯公式与高斯后验推导卡尔曼滤波的静态版概率推导题里有一道出镜率很高的题已知先验分布是正态分布N(μ0, σ0²)观测似然是N(x, σ²)求后验分布的均值和方差。这道题看起来是在考高斯分布的性质实际上是卡尔曼滤波更新步的静态版本。推导的步骤可以这样写后验概率正比于先验乘以似然所以对数形式为(μ - μ0)² / (2σ0²) - (x - μ)² / (2σ²) 常数展开之后把所有含μ²、μ的项合并整理成关于μ的二次函数。因为高斯分布是共轭的后验仍然是高斯分布直接对照系数就能得到后验均值 μ_post (σ² μ0 σ0² x) / (σ0² σ²)后验方差 σ_post² (σ0² σ²) / (σ0² σ²)答题的时候我建议在最后补一句工程语义这就是两个高斯传感器融合时置信度高的观测应该权重更大。评卷人看到这句话会觉得你是真的理解它在自动驾驶里的用途而不是只会套公式。3.3 反向传播手算链式法则的“傻瓜式”展开机器学习基础题里手算反向传播几乎是必考。常见的形式是给一个两层网络输入x、权重w1和w2、激活函数sigmoid、MSE损失求某个中间参数的梯度。我见过很多同学在草稿纸上直接写结果跳了好几层链式法则。这样做的风险是一旦中间某一步符号错了整个结果都是错的而评分老师找不到过程只能给零分。正确的做法是像拆洋葱一样一层一层写∂L/∂w2 ∂L/∂ŷ · ∂ŷ/∂z2 · ∂z2/∂w2 ∂L/∂w1 ∂L/∂ŷ · ∂ŷ/∂z2 · ∂z2/∂h · ∂h/∂z1 · ∂z1/∂w1每一步算一个具体的数最后再连乘。特别要注意sigmoid的导数形式σ(z)(1 - σ(z))漏掉这个因子是手算题失分最多的地方。这里还有一个易错点损失函数对输出层的梯度。如果使用MSE损失∂L/∂ŷ ŷ - y如果使用交叉熵配上sigmoid形式上会变成ŷ - y符号和系数要分清。笔试卷里如果出现选择题很喜欢在这个地方设陷阱。3.4 C智能指针考所有权比考语法多C工程题里我见过一个典型题目请说明shared_ptr和unique_ptr的区别并实现一个最简单的带引用计数的SharedPtr类。这个题不要求编译器能完整编译但要求设计思路清楚。unique_ptr独占对象所有权只能移动不能拷贝适合明确单一所有者的场景。shared_ptr采用引用计数允许多个智能指针共享同一个对象当引用计数归零时自动delete。weak_ptr不增加引用计数用来打破循环引用。一个简化版的SharedPtr实现思路是这样的类模板持有原始指针T* ptr和引用计数int* count。构造函数里ptr指向传入对象count指向一个新的int初始化为1。拷贝构造函数让新对象的ptr和count指向同一块区域然后(*count)。析构函数里(*count)--如果归零就delete ptr和delete count。赋值运算符要先处理自赋值再减少左侧旧对象的引用计数最后拷贝右侧指针和计数。这道题考的是RAII思想资源获取即初始化析构函数负责释放。如果只是背代码很容易在“赋值运算符的先减后加”上出错。实际工程中很多人因为循环引用问题把shared_ptr用出一堆内存泄漏所以笔试卷里经常附带一题weak_ptr怎么解决循环引用。回答时提一个例子两个类互相持有对方的shared_ptr导致引用计数永远不为零改成weak_ptr就能打破这个环。4. 避坑复盘这些错误我当年都踩过4.1 没看数据规模第一题就写了暴力解法我自己的排序第一道算法题时看到“合并区间”下意识就写了O(n²)的双重循环对每个区间遍历所有其他区间判断重叠再合并。小样例跑得飞快但一旦区间数量上到10^6运行时间直接爆炸。排查过程大概是这样的先看题目给的输入约束n最大10^6O(n²)意味着10^12次操作任何评测系统都扛不住。正规的OJ通常要求1秒到2秒内跑完按每秒10^8次简单操作估算O(nlogn)才是合理范围。遇到这种题第一步不是写代码而是先算复杂度把数据规模代入常见复杂度的数量级里过一遍。这道题的正确做法就是我前面写的排序加扫描。如果你在笔试现场发现自己第一版写复杂了不要慌在剩余时间里稳扎稳打把排序版本写出来即使晚几分钟提交也远好过一个超时的版本。吃一堑长一智后面我每次拿到题目都先看取值范围再定算法。4.2 概率推导题只写最终公式被扣到怀疑人生第二件让我印象很深的事是数学推导题我上来就写了后验均值公式没有过程。当时我觉得答案是对的应该没问题结果出来后比预期低了一截。后来跟同批笔试的同学交流大家一致的结论是评卷更看重过程只看结果没法判断你是不是真的掌握。从那以后我给自己立了一个规矩所有推导类题目不管简答还是填空都把关键步骤写出来。哪怕只是草稿式的几步也能让评分人看到你的思路。公式推导不写过程就像面试时只报学校不聊项目信息量完全不够。另外还要注意单位、符号的规范性。均值μ、方差σ²这些符号如果写混了整个表达式看起来会很乱。保险起见下笔之前先把“已知量”和“未知量”列清楚。4.3 C代码本地能跑在线OJ上却编译失败有段时间我特别容易在一个点上栽跟头本地CMake工程能编译也跑得通但把代码贴到笔试在线编辑器里就报编译错误。排查下来发现原因通常有三类缺少必要的头文件。本地环境可能因为预编译头文件或者IDE自动补全漏include也能过但在线OJ是gcc直接编译缺一个#include 就是编译错误。使用了C标准库新特性但在线环境编译器版本太老。比如结构化绑定、std::optional在C17才支持如果评测机的gcc默认是C14直接编译不过。自定义变量名和系统宏冲突。比如有人喜欢用data、left、right在某些环境里没问题但有些OJ会因为这些名字撞了系統内部定义而出错。解决方法是笔试前专门去自己目标公司的模拟环境或主流OJ适应几轮把“本地能跑”和“在线能跑”的差距提前抹平。笔试过程中如果遇到编译错误优先检查头文件和编译标准而不是反复调业务逻辑。4.4 时间分配失误被最后的附加题拖死图森未来2020校招笔试卷一到底是2小时还是更长不同批次可能有差异但通用策略都一样先把能拿的分全部拿到再考虑冲击难题。我认识一个同学前面有几道选择填空明明会做但为了死磕最后一道附加题花了四十多分钟结果附加题没写出来前面的题也没时间检查白白丢掉很多基础分。我的建议是拿到卷子先花2分钟通读一遍给每道题预估一个时间上限硬性执行。编程题单题超过30分钟没思路立刻换下一道数学推导超过15分钟没头绪先跳过。留出最后10分钟检查编译环境和基础题答案这个保底策略比追求一题满分重要得多。5. 针对自动驾驶笔面试的备考清单5.1 刷题范围与优先级如果目标是图森这类自动驾驶公司刷题范围要比普通互联网公司更聚焦。我推荐的优先级是这样的第一梯队数组、哈希表、双指针、二分查找、链表、栈、队列。这些是几乎所有笔试的第一题涉及范围必须做到闭着眼能写。第二梯队二叉树遍历、DFS/BFS、动态规划、贪心。中等难度的动态规划是区分度最高的题背包、子序列、编辑距离都属于高频。第三梯队图论基础、并查集、拓扑排序、前缀和、差分数组、线段树。这些在自动驾驶地图、路径规划相关的场景里会出现虽然不是每套卷都考但考到就是拉分题。除了LeetCode我也建议做一些经典算法手写题比如快速排序、归并排序、二分查找手写这些看起来基础但面试官和笔试评分都很看重代码的准确率。不要只刷会做的题要专门针对自己的薄弱类型做限时训练。5.2 数学与深度学习知识点自查表我把容易考的数学和深度学习知识点列成一张自查表每一条都能给自己打分知识点掌握程度要求条件概率、全概率公式、贝叶斯公式能默写并会用常见分布正态、均匀、伯努利、泊松知道表达式和期望方差最大似然估计能对正态分布/逻辑回归做完整推导高斯分布的乘积能推导归一化后的均值和方差卡尔曼滤波预测/更新公式理解每一步的物理含义链式法则与反向传播能手算两层网络梯度常见损失函数知道优缺点和求导结果L1/L2正则化能从先验角度解释差异优化器演变能讲清SGD到Adam的变化动机常见网络结构CNN、RNN/LSTM、Transformer的基本模块可以逐个去查漏补缺。不要只看答案每个知识点都尝试“不看书推一遍”推不出来再重新看。数学和机器学习这类内容看懂了和写出来完全是两回事。5.3 临场答题的实操策略最后这部分是纯经验希望你不是踩过坑才信。提前一周拿几套模拟题在真实计时环境中做培养节奏感。笔试当天提前找一个网络稳定的地方提前打开在线平台先确认编译环境支持的C版本和可用选项。拿到试卷后头两分钟用来“扫描”而不是“做题”。看清一共有几道题、每题分值、预计难度分布。然后按照“先易后难、先必得分后加分题”的顺序推进。编程题如果时间紧张先写一个正确但可能不是最优的解法拿到基础分再回头优化总比空着强得多。还有个细节很少人提笔试结束前的最后几分钟一定不要用来发愣。回头看看有没有漏题、文件名或格式要求有没有出错代码里有没有删除调试输出。很多认真做题的人最后挂在“忘记注释调试信息”这种小问题上真的可惜。我在实际准备过程中最大的体会是笔试更像是一个“状态管理”问题而不是单纯的知识储备问题。知识储备到位了临场能不能稳定发挥取决于你对时间、难度和心态的调度。图森未来2020校招笔试卷一这套卷子给我的启发不是哪道题考了多少分而是它让我提前把“算法、数学、机器学习、C”这根能力链条完整地过了一遍。如果你也准备走自动驾驶这条路线不妨把这份清单当成一个起点一项一项补齐比到处找原题猜测要靠谱得多。