ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

小满秋招算法岗笔试复盘:KMP、卡尔曼滤波与融合定位

小满秋招算法岗笔试复盘:KMP、卡尔曼滤波与融合定位 1. 笔试整体布局与考察方向分析1.1 小满秋招算法岗笔试的定位2023年度小满秋招算法岗第一批笔试整体来看更偏向车载感知与规控方向和传统互联网大厂那种纯刷题风格的笔试题有不少差异。小满的业务重点集中在智能驾驶、座舱交互、整车控制这些领域所以笔试题里能明显感受到“工程落地优先”的倾向——不会问你特别偏门的数学证明也不会让你手推复杂的收敛性分析更多是考察你能不能把经典的算法模型用到真实的工程场景里。第一批笔试的题型大致分三块选择题约40%、手写代码题约35%、简答与方案设计题约25%。总时长120分钟题量不算大但每一道题都需要深度思考尤其是方案设计题几乎没有标准答案考官看的是你的分析路径和工程判断力。这一批笔试比较有代表性的几个关键词是KMP的next数组计算、卡尔曼滤波在融合定位中的应用、PID与FOC在电机控制中的区别、以及一道融合了贪心策略与动态规划的工程优化题。单看每个知识点都不算超纲但组合在一起就能感受到小满对候选人的期待基础算法能力扎实同时对车辆控制、传感器融合这些领域有真实的理解。1.2 适合谁参考这份复盘如果你是准备自动驾驶算法岗、机器人控制岗、或者车载嵌入式AI岗的应届生这份复盘值得认真看。即使你不投小满这套笔试题的考察逻辑也代表了2023年智能驾驶赛道算法岗的主流风格——不追求竞赛级难度更看重你把算法用对地方的能力。反过来如果你纯刷LeetCode、准备的是通用后端或纯推荐系统算法岗这份笔试题的参考价值会打一些折扣因为侧重点明显不同。小满笔试里的代码题难度大约对标LeetCode中等偏下但简答题和方案设计题的区分度非常高很多刷题高手反而在这里翻车。坦白说我参加这场笔试前也走了弯路花了大量时间刷hard题结果代码题难度不大方案设计题反而答得磕磕绊绊。所以这篇复盘我会把重点放在“怎么从题目反推考察意图”上而不是单纯对答案。2. 核心考点深度拆解算法原理与选型逻辑2.1 字符串与模式匹配KMP的next数组到底在考什么笔试选择题里有一道很典型的KMP题对于模式串 p “abacaba”要求计算next数组并说明当主串在第7个字符失配后模式串应该如何移动。这道题看起来基础但错误率非常高原因在于很多人背了模板却没有真正理解next数组的语义。在KMP算法中next[i]的定义是模式串p的前i个字符组成的子串中最长的相同前缀后缀长度有的教材定义为最长真前缀后缀长度实际编码时边界会有差异。以“abacaba”为例手动推导一遍next[0] -1哨兵表示无匹配next[1] 0子串“a”没有真前后缀next[2] 0子串“ab”最长相等前后缀长度为0next[3] 1子串“aba”最长相等前后缀为“a”next[4] 1子串“abac”最长相等前后缀为“a”next[5] 2子串“abaca”最长相等前后缀为“ab”next[6] 3子串“abacab”最长相等前后缀为“ab”不对子串的前6个字符是“abacab”前缀“aba” 后缀“cab”不等于前缀“ab”后缀“ab”所以长度为2。重新推子串“abacab”的最长相等前后缀是“ab”长度为2。所以整个next数组是[-1, 0, 0, 1, 1, 2, 3]不对next[6]对应前6个字符“abacab”最长相等前后缀是“ab”长度为2。而next[7]对应完整模式串最长相等前后缀是“aba”长度为3。如果题目考察的是包含完整串的next值那最后一位是3。这里有个非常容易踩的坑不同的教材和实现方式next数组的下标和边界定义不一样。有的从1开始计数有的把next[0]定义为-1有的定义为0。实际笔试时别急着写代码先看清楚题目对next的定义再作答否则很容易在选项里迷失。我当时在这道题上花了4分钟就是因为一开始记混了定义重新推导才算对。2.2 经典数据结构的工程意义排序与查找的选型博弈小满这批笔试的选择题里排序算法考得很有意思不直接问时间复杂度而是给了一个具体工程场景问你会选哪种排序。大意是嵌入式平台上有大约5000条车辆CAN信号日志每条日志有一个时间戳希望按时间戳排序后输出内存只有几百KB请问你会选择哪种排序方案这个场景如果你只是背了“快速排序平均O(nlogn)”就答很容易掉坑。因为嵌入式平台上递归深度是受限的数据量5000不算大但递归栈不可控标准快排在最坏情况下可能退化成O(n²)且栈溢出。而堆排序是原地排序、空间复杂度O(1)、最坏时间复杂度稳定在O(nlogn)更适合这个场景。不过如果你再往深处想这类日志往往存在时间相近的局部有序性插入排序或希尔排序在近有序数据上的实际性能往往比堆排序更好。但选择题有标准答案结合嵌入式内存受限约束堆排序应该是考官的预期答案。做题时我提醒自己算法题一旦结合工程场景就不能只背复杂度还要考虑空间、稳定性、递归、数据分布这些现实因素。2.3 数值与滤波算法卡尔曼滤波为什么是融合定位的基石简答题有一道在GNSS/IMU融合定位中说明卡尔曼滤波的预测和更新两个步骤分别解决了什么问题并解释协方差矩阵在其中的作用。这道题考察的是对卡尔曼滤波原理本质的理解而不是背公式。预测步骤解决的是基于运动模型比如IMU的加速度和角速度积分估计当前时刻的状态先验同时用过程噪声矩阵Q来表达模型误差的不确定性。更新步骤解决的是当GNSS观测到达时如何用观测值修正先验估计卡尔曼增益K的本质是在预测不确定性和观测不确定性之间做加权谁的协方差小谁就更可信。我当时在答案里画了一个很关键的关系说明卡尔曼增益与观测噪声矩阵R成反比与先验协方差成正比。如果R很大说明观测不可靠K变小滤波结果更信任预测值如果过程噪声Q很大说明模型漂移严重K变大滤波结果更信任观测值。这个权衡逻辑才是卡尔曼滤波能够在传感器融合中被广泛使用的原因。我还强调了一点协方差矩阵P不只是数字它代表了对状态估计的置信区间。在GNSS信号丢失的隧道场景中P会不断增大表示位置估计越来越不可信此时如果重新收到GNSS信号K会被拉大系统会迅速向观测值靠拢。这个思考让答案有了工程落地感而不是干巴巴的公式推导。2.4 控制与优化算法PID、FOC与智能优化算法的适用边界笔试里有一道让我印象深刻的题目在车辆永磁同步电机的FOC控制中电流环通常采用PI控制器而速度环可以采用PID控制器请解释两者的区别并说明为什么电流环不适合加入微分项。这题考的是对控制算法的工程理解。电流环是FOC的最内环响应速度要求极高控制周期一般在微秒到十几微秒级别。如果加入微分项微分对高频噪声极其敏感而电流采样本身带有开关噪声微分项会把噪声放大导致电流脉动、转矩波动严重时甚至会引起系统震荡。所以工程上电流环通常用PI就够了P保证响应速度I消除稳态误差。速度环因为惯性大、响应慢微分项有助于抑制超调所以可以用完整PID。这道题如果你只背PID三个字母的含义不知道电流环和速度环的时间尺度差异很难答出深度。再延伸一下热词检索里出现了粒子群算法、模拟退火算法这类智能优化算法虽然不直接出现在这批笔试代码题里但在方案设计题中可以作为“参数自整定”的思路提一嘴。比如用粒子群算法离线整定速度环PID参数再结合模糊控制做在线调整。这种回答能体现出你的知识面广度但要注意别跑偏考官更想看到你对经典算法的深刻理解而不是堆砌一堆新名词。3. 实操过程与代码级复盘3.1 手写代码题一基于贪心与双指针的区间合并代码题第一道非常经典给定若干区间合并所有重叠区间输出合并后的区间列表。输入是二维数组每个子数组包含[start, end]输出要求按start升序排列。这道题思路不难先按start排序再遍历区间维护一个当前合并区间的右边界。如果下一个区间的start小于等于当前右边界说明重叠更新右边界为两者最大值否则把当前区间加入结果开始新的区间。核心代码如下def merge_intervals(intervals): if not intervals: return [] intervals.sort(keylambda x: x[0]) res [] cur_start, cur_end intervals[0] for start, end in intervals[1:]: if start cur_end: cur_end max(cur_end, end) else: res.append([cur_start, cur_end]) cur_start, cur_end start, end res.append([cur_start, cur_end]) return res这道题真正的考点有两个一是排序key的正确选择很多人在自定义二维数组排序时写错二是边界条件比如空数组、只有一个区间、相邻区间是否算重叠start cur_end 时算重叠如果要求严格不相交则改为。我当时在实现时额外考虑了内存优化如果直接在原数组上操作可以把排序后的数组原地复用减少一次结果数组的拷贝。虽然笔试不强制要求但这种细节能体现工程意识。坦白说这道题没有太多坑唯一需要注意的是别用递归实现排序数据量大时容易栈溢出。3.2 手写代码题二快速幂与取模运算的边界处理另一道代码题是计算 a 的 n 次幂对 1e97 取模的结果n 的范围可达 10^18。这就是典型的快速幂模板题但小满做了一点变化a 和 n 都可能不是正整数n 可能为负数。如果 n 是负数需要先求 a 的逆元在模素数下用费马小定理再对 |n| 做快速幂。完整代码如下MOD 10**9 7 def pow_mod(a, n): if n 0: a pow(a, MOD - 2, MOD) # 费马小定理求逆元 n -n res 1 a % MOD while n 0: if n 1: res (res * a) % MOD a (a * a) % MOD n 1 return res这里有个特别容易踩的坑a 可能不是素数模的互素元素如果 a 是 MOD 的倍数比如 a MOD那么 a % MOD 0此时负指数幂没有定义0没有逆元。这种边界条件题目没明说但实际工程里一定得处理。我加了一行判断如果 a % MOD 0 且 n 0直接返回-1或抛异常。代码量不大但体现了对模运算的深入理解。热词里也提到了“快速幂算法c”如果面试官要求你用C实现还得注意long long溢出问题。乘法中间结果先转long long再取模否则int类型会溢出导致结果错误。3.3 手写代码题三图论中的Dijkstra与堆优化第三道代码题是求带权有向图中从源点到所有点的最短路径图的边权可能为负但保证不存在负权环。很多人看到可能为负就慌了实际上如果边权可能为负但不能为负环Bellman-Ford或SPFA才能处理Dijkstra在负权边下会失效。这道题的正确解法应该是SPFA或者Bellman-Ford。我为什么说这道题很有代表性因为小满的考察点不是算法本身而是**“你是否知道Dijkstra的适用前提”**。很多刷题刷成惯性的人拿到“最短路径”就直接写堆优化的Dijkstra完全忽略负权边直接用堆优化的Dijkstra结果在负权样例上就会得到错误答案。批卷者其实是在看你能不能识别出这个坑。SPFA的实现复杂度不高但要注意负权环的检测一个点如果入队超过n次就说明存在负权环。代码如下from collections import deque def spfa(n, edges, source): adj [[] for _ in range(n)] for u, v, w in edges: adj[u].append((v, w)) dist [float(inf)] * n in_queue [False] * n count [0] * n dist[source] 0 q deque([source]) in_queue[source] True while q: u q.popleft() in_queue[u] False for v, w in adj[u]: if dist[u] w dist[v]: dist[v] dist[u] w if not in_queue[v]: q.append(v) in_queue[v] True count[v] 1 if count[v] n: return None # 存在负权环 return dist如果你只会Dijkstra而没掌握SPFA这道题就会很被动。这里也提醒大家刷题不应该只刷“模板题”而是要把每个经典算法的适用条件和限制搞清楚。3.4 手写代码题四基于动态规划的最长上升子序列变体最后一道代码题是求最长上升子序列长度但加了一个条件要求输出的不是长度而是有多少个不同的最长上升子序列的个数。这题需要一个二维DPdp[i]表示以第i个元素结尾的最长上升子序列长度cnt[i]表示以第i个元素结尾的、长度为dp[i]的上升子序列个数。转移时如果dp[j] 1 dp[i]则更新dp[i]同时cnt[i] cnt[j]如果等于则cnt[i] cnt[j]。最后统计所有dp值等于全局最大值的cnt之和。核心代码def count_lis(nums): if not nums: return 0 n len(nums) dp [1] * n cnt [1] * n max_len 1 for i in range(n): for j in range(i): if nums[j] nums[i]: if dp[j] 1 dp[i]: dp[i] dp[j] 1 cnt[i] cnt[j] elif dp[j] 1 dp[i]: cnt[i] cnt[j] max_len max(max_len, dp[i]) total 0 for i in range(n): if dp[i] max_len: total cnt[i] return total这里的坑在于如果nums里有重复元素直接套经典LIS模板会统计重复的子序列需要考虑去重。我当时在答案里用集合去重的方式做了兜底虽然时间复杂度高了一点但保证了正确性。坦白说现场笔试的时间压力下这种“变种题”最容易暴露刷题背模板的问题。我和旁边几个考生交流过不少人在cnt[i] cnt[j]这一步漏掉了“多个不同前缀路径”的细节。4. 方案设计题解析与常见问题4.1 如何设计一个车载多传感器融合定位方案笔试的最后一道大题是方案设计在一个地下停车场场景中车辆无法接收GNSS信号需要设计一套融合定位方案使车辆在车道级精度下完成自主泊车。要求说明传感器选型、融合算法架构、异常处理三部分。这道题一出基本上就能拉开差距了。GNSS失效场景下常用的方案是轮速计IMU视觉/激光雷达的融合。轮速计和IMU组成航位推算Dead Reckoning但在长时间运行下会累积漂移所以需要视觉或激光雷达提供绝对观测来修正漂移。我给出的方案架构是用**误差状态卡尔曼滤波ESKF**作为融合框架将IMU作为运动预测输入轮速计提供速度约束视觉SLAM或激光点云匹配提供位置观测。在ESKF中IMU的陀螺仪和加速度计偏差被建模为状态向量的一部分这样可以实时估计并补偿传感器漂移。针对地下停车场的特殊场景我还补充了几点停车场柱子多、纹理少纯视觉方案容易丢特征所以主定位用激光雷达或UWB标签更稳在没有GNSS的长时间运行下需要定期做回环检测来消除累积误差如果车辆进入电梯口等动态场景雷达点云会出现大量动态障碍物需要做运动目标滤除这道题没有标准答案但如果你完全没接触过多传感器融合很容易写出“用GPSIMU就行”这种缺乏深度方案。建议准备智能驾驶方向的同学一定要理清楚各种传感器在融合架构中的角色——谁提供高频预测、谁提供低频修正、谁提供绝对约束。4.2 笔试现场的常见低级错误我在实际参加笔试时犯了一些低级错误写出来给大家避坑第一读题不仔细把“上升子序列”看成“非递减子序列”。虽然只差一个“非递减”但代码逻辑完全不同。尤其是数据里有重复元素时非递减要求nums[j] nums[i]而严格上升要求。建议动笔前先把题目的比较符号圈出来别省这一分钟。第二快速幂里的n类型写错。如果题目给的是Python int没事如果是C long long负数取模时一定要先转正否则位运算的结果是负数while循环直接不执行输出永远是1。第三区间合并题没有处理输入为空的情况。很多模板在intervals为空时直接取intervals[0]会越界这种小细节在笔试判分时会被扣分。第四方案设计题只答技术不答落地。比如设计融合定位只写了“用卡尔曼滤波”没有说明观测模型、状态维度、异常检测策略面试官会觉得你只是背了名词。要写出具体的工程链路至少让人看出你想过实现问题。4.3 排序与查找类笔试陷阱速查表整理一批笔试选择题里常见的排序和查找陷阱方便大家考前快速过一遍。考察点容易踩的坑正确的理解快速排序时间复杂度把最坏情况复杂度当作平均复杂度平均O(nlogn)最坏O(n²)有序数据且选固定基准时最坏堆排序空间复杂度以为堆排序需要额外数组原地建堆空间O(1)归并排序稳定性误以为所有O(nlogn)算法都不稳定归并排序是稳定的快排和堆排不稳定二分查找边界left right和left right搞混左闭右闭用左闭右开用循环条件决定了区间是否还有效哈希表冲突处理只记开放定址和链地址工程中链地址法更常用二次探测适合数据量可控的场景希尔排序增量序列以为增量固定为n/2增量序列选择影响性能不同序列复杂度从O(n^1.3)到O(n^2)不等在嵌入式环境下查找和排序还要额外考虑数据是否能在内存中完全放下如果放不下就涉及外部排序和多路归并。这类问题小满笔试没有直接出但在方案设计里可以补充提到。5. 备考策略与后期提升路径5.1 从热词看算法岗的备考方向这次的网络热词检索中出现了大量算法关键词粒子群算法、模拟退火、KMP、BM25、Sobel、卡尔曼滤波、PID、FOC、强化学习、聚类算法、Dijkstra、快速幂、Rete算法、HK算法等等。乍一看很杂但可以分成几条主线基础算法与数据结构KMP、排序、堆、快速幂、Dijkstra、二分图HK——这些是笔试代码题的底座必须烂熟于心机器学习与深度学习算法KNN、聚类、BM25、EVA-02分类、工业异常检测——这些更多出现在面试聊项目环节但笔试简答题偶尔会涉及基础概念控制与信号处理算法PID、FOC、卡尔曼滤波、Sobel、音频重采样——这正好对应了小满这类智能驾驶公司的业务方向工程优化与推理算法规则引擎Drools的Rete算法、KL ELBO推导、剪枝算法——这些属于加分项能体现你的知识广度我的建议是如果你明确投的是车载算法岗请把第3条主线作为重点而不是花大量时间刷偏门的神经网络结构。笔试和面试官更看重“你懂不懂这辆车是怎么跑起来的”。5.2 针对小满笔试的查漏补缺清单结合这次真题复盘我整理了一份自测清单你可以对照检查手写KMP的next数组能不能在3分钟内算对手写快速幂能不能处理负指数和取模逆元解释Dijkstra和SPFA的适用条件能不能举出Dijkstra失效的反例画出一个一维卡尔曼滤波的预测-更新流程图并说明每个矩阵的维度说清楚FOC电流环和速度环在控制周期、PID参数上的区别给定一个嵌入式内存受限场景你能不能在1分钟内说出该选什么排序算法如果面试官让你设计地下车库融合定位方案你能不能说出ESKF的核心思路以上7个问题如果你能不看资料就答出来小满这批笔试的难度对你来说不会太高。如果卡壳了就赶紧回去补课。5.3 我给下一届考生的几点非技术建议最后说几条非技术层面的经验因为笔试不只是考知识也考体力、心态和时间管理。第一提前模拟真实笔试环境。小满用的是在线笔试平台支持本地IDE调试但自动判题时用的是不同测试用例。建议考前找几套模拟题严格计时120分钟练练在屏幕上读长题干的感觉。纸质刷题和屏幕刷题完全是两种体验屏幕阅读速度慢容易漏掉关键条件。第二代码题的输入输出处理要熟练。笔试平台有时候会要求自己处理标准输入输出比如读取多行整数、字符串切分。如果你不熟悉sys.stdin.readline和split的用法很容易在IO上浪费时间。可以提前准备一个常用IO模板考试时直接套用。第三方案设计题不要留白。即使你对多传感器融合不了解也要写出你的思考框架环境约束分析、可选传感器、精度需求拆解、融合策略、失效兜底。批卷者想看的是你的分析能力而不是标准答案。留白是零分写一部分至少能拿到过程分。第四注意心理预期。第一批笔试通常会有很多候选人同场竞争压力大但心态真的会影响审题。如果你遇到一道题卡了5分钟先跳过做后面的不要死磕。我因为前面KMP推导纠结太久导致后面方案设计题时间紧写得很仓促。时间分配上我建议选择题控制在30分钟内代码题每题20分钟方案设计题至少留30分钟。5.4 笔试之后还能做点什么笔试结束后很多人就干等着结果。我建议你利用这段时间做一件事把笔试中暴露的知识盲区整理成一份错题本按算法类别归档。比如这次如果KMP的next数组算错了就把KMP的完整推导过程写一遍如果卡尔曼滤波的协方差矩阵含义说不清楚就画一个一维例子手动算一遍更新过程。这份错题本在后续面试中非常有用因为很多面试官会从笔试题目出发问你“当时为什么这么答”。另外可以顺着笔试中出现过的工程场景做一次知识延伸。比如小满考了FOC电流环PI控制你就可以去了解整个FOC控制链路Clark变换、Park变换、SVPWM调制。这些知识在职后面试和实际工作中都会用到而且能让你在答方案设计题时更有底气。根据我的实际经验秋招笔试的暴露面往往比面试更广它像一个雷达扫描把你知识体系里的薄弱环节全暴露出来。认真复盘把每一个盲区补上比海量刷题更有效。我自己就是从这批笔试开始系统地补了一遍状态估计和控制理论后面的面试明显顺畅了很多。
返回列表