news 2026/8/31 13:57:37

途虎养车2023秋招算法笔试题解析:从KMP到业务场景

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
途虎养车2023秋招算法笔试题解析:从KMP到业务场景

1. 看一份算法笔试卷,先看它在筛选什么

说到“途虎养车2023秋招算法笔试试卷A”,很多准备秋招的同学第一反应是到处找原题、背答案。我做了几年算法工程师,也参与过校招笔试出题和面试,这里先说一个可能不太中听但很真实的话:你几乎不可能拿到某家公司某一年完整的原卷。笔试题目是内部资产,流出概率极低,网上能搜到的多是零星回忆版。但这不代表这份试卷对你没有参考价值——恰恰相反,只要看懂一份有代表性的算法笔试卷在考察什么,你就能推出一类公司的出题风格和筛选逻辑。

途虎养车做的是汽车后市场,业务核心是供应链、门店履约、用户增长、定价补贴、推荐搜索这些方向。这种偏产业互联网的公司,算法岗笔试不会像头部大厂那样疯狂堆困难动态规划,也不会像纯AI实验室那样上来就考论文复现。它的考察重心通常是:数据结构与算法的基础扎实程度、机器学习/深度学习的基础理解、以及把算法落到真实业务场景的工程思维

对于准备这类笔试的同学,我的建议是把注意力从“找原题”转移到“拆解考点”上。一份试卷A也好、B卷也好,换汤不换药的核心考点就那么几类:字符串与KMP、排序与堆、贪心与动态规划、树与图、机器学习基础、优化算法原理。与其焦虑“这份卷子考了什么”,不如问自己:“如果我是出题人,我会用哪些题来区分有没有真实力的候选人?”

2. 字符串与KMP:一道题就能看出基本功

2.1 next数组的计算逻辑,不能只会背代码

在算法笔试里,KMP 算法几乎是字符串专题的“钉子户”。很多热搜词里能看到“在KMP算法中,对于模式串p='abacaba',其next数组”这类问题,说明这也是高频考点。KMP 的核心不是匹配过程本身,而是next 数组的构建是否真正理解

我见过太多候选人能把 KMP 匹配的代码默写出来,但一问 next[i] 到底代表什么就含糊了。这里我习惯用一句话解释:next[i] 表示模式串前 i 个字符组成的子串中,最长相等前缀和后缀的长度(通常不包含自身)。注意这个“不包含自身”,很多人就是栽在这里。

拿 p="abacaba" 举例,我们一步步推:

i=0:next[0] = -1(或0,看具体实现约定) i=1:子串"a",没有真前缀和真后缀相等,next[1] = 0 i=2:子串"ab",前缀"a"后缀"b"不等,next[2] = 0 i=3:子串"aba",前缀"a"=后缀"a",next[3] = 1 i=4:子串"abac",前缀"ab"后缀"ac"不等,但前缀"a"=后缀"c"?不,next[4] = 0 i=5:子串"abaca",前缀"ab"=后缀"ca"?不,前缀"a"=后缀"a",next[5] = 1 i=6:子串"abacab",前缀"aba"=后缀"cab"?不,前缀"ab"=后缀"ab",next[6] = 2 i=7:子串"abacaba",前缀"abac"后缀"caba"?不,前缀"aba"=后缀"aba",next[7] = 3

所以 next 数组是[-1, 0, 0, 1, 0, 1, 2, 3](按 next[0]=-1 的约定)。笔试里如果出选择题,通常会给几组数组让你选;如果出编程题,就要求你实现getNext()并完成匹配。

这里有个实操技巧:KMP 的 next 数组有两种主流约定。一种是 next[0] = -1,另一种是 next[0] = 0,两者在匹配回退时的下标处理不同。如果你习惯背模板,务必在笔试前固定一种写法并反复练习,不要考场上临时切换。我在牛客网刷题时习惯用next[0] = -1的版本,因为匹配时j = next[j]的逻辑更统一。

2.2 字符串题型的“隐藏考点”与实战选择

除了 KMP 本身,笔试卷里字符串题还常考:最长公共前缀、字符串哈希、回文串(Manacher)、字典序比较等。这些题单看难度不高,但容易在边界条件上翻车。

举个实际例子:实现strStr()(在主串中找模式串第一次出现的位置)。暴力法 O(n*m) 在字符串长度上万时就会超时,所以 KMP 是标准答案。但有一种更取巧的做法:用 Python 的find()一行解决。笔试系统如果允许,能过;但我不建议依赖这个,因为面试追问时你会很难堪。更好的做法是用字符串哈希(Rolling Hash),把匹配问题转化为哈希值比较,配合前缀哈希数组,能在 O(n) 内解决,而且代码比 KMP 好写很多。

字符串哈希需要选好基数和模数,我常用的组合是base = 131mod = 1e9+7。注意处理哈希冲突时,可以双哈希兜底:

class StringHash: def __init__(self, s): n = len(s) self.h1 = [0] * (n + 1) self.h2 = [0] * (n + 1) self.p1 = [1] * (n + 1) self.p2 = [1] * (n + 1) b1, m1 = 131, 10**9 + 7 b2, m2 = 137, 10**9 + 9 for i in range(n): c = ord(s[i]) self.h1[i+1] = (self.h1[i] * b1 + c) % m1 self.h2[i+1] = (self.h2[i] * b2 + c) % m2 self.p1[i+1] = (self.p1[i] * b1) % m1 self.p2[i+1] = (self.p2[i] * b2) % m2 # 注意实际使用时需要分别存储两个哈希的数组 def get(self, l, r): # 计算区间 [l, r) 的哈希值 # 双哈希返回元组,降低冲突概率 pass

笔试里字符串题的正确策略是:优先考虑能 AC 的稳妥方案,在足够时间基础上再追求最优解。如果你 KMP 写不熟,先用哈希做出来,保底拿分,比死磕 KMP 导致整题放弃强得多。这是我刷了三百多道题后最深的一个体会——笔试是按通过率给分的,部分分也有价值。

3. 排序与数据结构:堆排序、快排的工程化思考

3.1 经典排序算法不只是背诵时间复杂度

热搜词里“数据结构排序算法”“堆排序算法”都在前列。排序算法在笔试里出现的形式通常是:手写快排/堆排、求第 K 大/第 K 小、排序稳定性判断、自定义比较器。

以堆排序为例,很多人能背出“建堆 O(n),调整 O(n log n)”,但手写heapify时经常出问题。堆排序的核心操作是sift_down(下沉),而不是sift_up。建堆时从最后一个非叶子节点开始倒着做下沉,这个细节不少人会忘。

def heapify(arr, n, i): largest = i left = 2 * i + 1 right = 2 * i + 2 if left < n and arr[left] > arr[largest]: largest = left if right < n and arr[right] > arr[largest]: largest = right if largest != i: arr[i], arr[largest] = arr[largest], arr[i] heapify(arr, n, largest) def heap_sort(arr): n = len(arr) # 建堆:从最后一个非叶子节点开始 for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i) # 逐个取出堆顶 for i in range(n - 1, 0, -1): arr[i], arr[0] = arr[0], arr[i] heapify(arr, i, 0)

这里有一个容易被忽略的考点:求 Top K 问题时,用堆排序的变体(维护大小为 K 的小顶堆)复杂度是 O(n log K),而用快速选择(Quick Select)是平均 O(n)。如果题目只要求 Top K 且不要求有序输出,Quick Select 更优。但 Quick Select 的缺点是快排 partition 过程容易写错、最坏 O(n^2),所以笔试时我通常先写堆方案保底,时间充裕再优化。

3.2 排序算法在业务题里的变形

笔试里排序通常不是单独考,而是作为工具嵌在业务题里。比如:“途虎养车有 n 个门店,每个门店有若干订单,请你按订单量从高到低输出门店 Top 10”——这本质上就是 Top K + 稳定排序问题。

再比如自定义排序:sort(key=lambda x: (-x[1], x[0]))这种写法在 Python 里很常见,但有些同学对多关键字排序的交换顺序不熟。Python 的 sort 是稳定排序,这意味着你可以连续调用两次 sort 实现多级排序;但更推荐直接用 tuple 作为 key,因为元组比较天然支持多关键字。Java 里则是用Comparator链式调用。

我在笔试中见过一个高频业务题变体:区间合并。给出一组门店服务半径区间,合并重叠区间,输出合并后的数量。这题就是先按起点排序,再维护当前覆盖终点做贪心合并,核心是排序后的一次扫描。这类题考的不是排序算法本身,而是“能不能想到先用排序把无序问题变成有序问题”。

4. 机器学习与深度学习算法:从原理到场景题

4.1 KNN、K-Means 与聚类算法的高频考点

搜索热词里“knn算法的应用能力包括哪三个方面”“聚类算法”排名靠前。机器学习基础题在算法笔试试卷中占比不低,尤其是非纯研究岗。以 KNN 为例,常考这么几个点:

  1. K 值选择:K 太小容易过拟合,太大容易欠拟合,常用交叉验证选取。
  2. 距离度量:欧氏距离、曼哈顿距离、余弦相似度各自的适用场景。
  3. 特征归一化:KNN 依赖距离计算,量纲不一致时数值大的特征会主导距离,所以必须先标准化/归一化。

这三个点不仅是笔试选择题的考点,也是场景题的基础。比如题目说“用户画像相似度计算,用 KNN 做用户分群,特征有年龄、消费金额、浏览时长”,你就要反应过来:年龄和消费金额量纲不同,必须先做标准化;同时用户分群更适合用无监督的 K-Means 而不是 KNN,因为 KNN 需要标签。

K-Means 的考点则集中在:K 值怎么选(肘部法则)、初始中心点怎么选(K-Means++)、收敛条件、对离群点敏感。我在面试中经常追问:K-Means 一定能收敛吗?答案是能收敛到局部最优,但不是全局最优,所以需要多次随机初始化取最优结果。这个细节笔试里可能不会直接考,但面试会。

4.2 深度学习基础:激活函数、过拟合与优化器

深度学习在笔试里通常不会让你手推反向传播,更多是基础概念题。比如:Sigmoid 和 ReLU 的优缺点对比、过拟合的解决方案(正则化、Dropout、早停、数据增强)、常见优化器(SGD、Momentum、Adam)的区别。

这里有个容易混淆的点:Adam 一定比 SGD 好吗?笔试如果出选择题,大概率会问“以下哪个优化器引入了动量概念”,答案是 Momentum 和 Adam。但实际工程里,Adam 在训练初期收敛快,后期容易在最优解附近震荡;SGD 配合合适的学习率调度有时泛化更好。我在实际业务模型训练中通常先用 Adam 快速找到一个好的起点,再切 SGD 微调。

场景题方面,途虎这类公司可能出这样的题:“用户点击预测模型中,正负样本比例 1:99,你会怎么处理?”标准答法包括:过采样/欠采样、调整分类阈值、使用 Focal Loss、评估指标用 AUC/PR 而不是 Accuracy。这类题没有唯一答案,考察的是你有没有真正调过模型、踩过数据不平衡的坑。

5. 优化算法与场景结合:粒子群、模拟退火与PID

5.1 启发式算法:粒子群和模拟退火的原理与应用

看到热搜词里有“粒子群算法原理”“模拟退火算法”“pid算法在crps psu power的作用”,说明这批热词背后有相当一部分人在搜索优化算法相关的内容。虽然途虎养车的算法笔试未必会考到粒子群这种相对冷门的内容,但作为算法工程师,这类优化算法的原理最好还是了解,尤其是做供应链排程、路径规划、定价优化时,启发式算法是常用工具。

粒子群算法(PSO)的核心思想是模拟鸟群觅食:每个粒子是解空间中的一个候选解,拥有位置和速度,每次迭代根据个体最优(pBest)和全局最优(gBest)更新速度与位置。公式是:

v = w * v + c1 * r1 * (pBest - x) + c2 * r2 * (gBest - x) x = x + v

其中 w 是惯性权重,c1、c2 是学习因子,r1、r2 是 [0,1] 随机数。代码实现其实只要三十行左右:

import random def pso(fitness, dim, n_particles=30, max_iter=100): # 初始化粒子位置和速度 particles = [[random.uniform(-10, 10) for _ in range(dim)] for _ in range(n_particles)] velocities = [[random.uniform(-1, 1) for _ in range(dim)] for _ in range(n_particles)] pBest = particles[:] pBest_score = [fitness(p) for p in particles] gBest = pBest[pBest_score.index(max(pBest_score))] gBest_score = max(pBest_score) w, c1, c2 = 0.7, 1.5, 1.5 for _ in range(max_iter): for i in range(n_particles): for d in range(dim): r1, r2 = random.random(), random.random() velocities[i][d] = (w * velocities[i][d] + c1 * r1 * (pBest[i][d] - particles[i][d]) + c2 * r2 * (gBest[d] - particles[i][d])) particles[i][d] += velocities[i][d] score = fitness(particles[i]) if score > pBest_score[i]: pBest[i] = particles[i][:] pBest_score[i] = score if score > gBest_score: gBest = particles[i][:] gBest_score = score return gBest, gBest_score

模拟退火(SA)的核心是 Metropolis 准则:以一定概率接受更差的解,且这个概率随温度下降而减小。它比 PSO 简单,但容易调参。笔试题如果出“求函数 f(x) = x^2 在 [-5,5] 的最小值”,用模拟退火和用梯度下降都能解,但概念题更常问:SA 跳出局部最优的机制是什么?答案是概率接受准则。

5.2 PID 控制与工程场景中的算法思维

PID 算法出现在热词里有点意外,但仔细想也很合理——途虎养车做汽车后市场,车联网、智能硬件、门店设备的温控、电机控制等场景都可能涉及 PID。虽然算法笔试考 PID 的概率不高,但如果你是做 IoT 方向或汽车相关算法岗,PID 就是标配知识。

PID 三个环节的作用分别是:P(比例)根据当前误差输出控制量,让系统快速接近目标;I(积分)消除稳态误差,但积分过大容易超调;D(微分)抑制误差变化速度,减小震荡。调参的工程口诀是“先 P 后 I 再 D”,我在实际调试温控系统时也是这个顺序:先把 P 调到一个临界值,系统开始震荡后再加 D 抑制,最后加 I 消除静差。

从笔试角度,如果出一道 PID 相关场景题,大概率是“如何让一个温度控制系统更快达到设定值并减少超调”。标准答法无非是:增大 P 提升响应速度,引入 D 抑制超调,精细化调参或使用模糊 PID 自适应。说到底,这考的是控制论+工程直觉,而不是背诵公式。

6. 从笔试卷面到真实业务:那些刷题刷不来的能力

6.1 算法题之外的业务场景题怎么准备

回到“途虎养车2023秋招算法笔试试卷A”这个题目本身,我虽然拿不到原卷,但根据途虎的业务模式可以合理推测:试卷里除了纯算法题,大概率还有业务场景题。比如:

  • 如何预测某个城市未来一周的保养订单量?(时间序列预测 + 特征工程)
  • 如何给新用户推荐合适的轮胎/保养套餐?(召回 + 排序)
  • 如何为不同门店分配优惠券预算,使得 ROI 最大化?(约束优化)

这类题的共同特征是:没有标准答案,考察的是你把算法问题映射到业务问题的能力。我建议准备时用“问题定义 → 数据选择 → 特征设计 → 模型选型 → 评估指标 → 上线方案”这个框架来组织回答。哪怕你没有实际做过这个业务,按这个逻辑说也能让面试官觉得你有系统思维。

举个例子,订单量预测题,我会这样拆:

  1. 问题定义:预测粒度是“城市×天”还是“城市×门店×天”?这决定数据量和模型复杂度。
  2. 特征设计:历史订单量、星期几、节假日、天气、油价、促销活动、门店数量变化。
  3. 模型选型:基线用 HA(历史平均)或 ARIMA,进阶用 LightGBM 或 Prophet,数据量足够再试 LSTM/Transformer。
  4. 评估指标:MAPE、RMSE,注意订单量存在明显的周期性,MAPE 可能比 RMSE 更合理。
  5. 上线方案:先用离线评估,再用 shadow 模式小流量灰度,对比线上效果。

6.2 刷题建议:从“会做”到“做得快、写得对”

最后聊聊大家最关心的备考节奏。我当年秋招的刷题量大概在 400 道左右(LeetCode + 牛客),不算多但足够用,关键在总结。我的刷题路线是“三阶段法”:

  • 第一阶段(基础期):按数据结构分类刷,数组、链表、栈、队列、哈希、树、图。每个数据结构至少刷 15 道,核心是把 API 和模板题练熟。
  • 第二阶段(题型期):按算法思想分类刷,双指针、二分、贪心、动态规划、回溯、DFS/BFS。每类集中刷 15-20 道,总结套路。
  • 第三阶段(模拟期):每周 2-3 次完整笔试模拟,限时 90 分钟做 3-4 道题,刻意训练时间分配。

关于时间分配,我的经验是:试卷发下来先花 3 分钟通读所有题目,按“会不会做”分三档。第一档(一眼有思路)马上写;第二档(有思路但不确定)先写大概率正确的部分;第三档(完全没思路)最后写,优先用暴力解或特判拿部分分。不要在一道题上卡超过 25 分钟,尤其是编程题,后面往往有更简单的题等着你。

还有一个容易被忽视的点:笔试环境一定要提前熟悉。不同公司用的笔试平台不一样(牛客、赛码、猿圈等),有的支持本地 IDE 粘贴,有的只能在网页上写,有的要自己处理输入输出。提前去对应平台做一套模拟题,比考前多刷十道题都管用。

7. 写在最后:算法笔试不是终点,而是起点

说句实在话,我工作几年后再回头看秋招笔试,发现那些算法题在真实业务里很少会原样出现。但准备笔试的过程——刷题、总结、复盘——锻炼出来的代码能力、逻辑思维和问题拆解能力,是实打实带到工作中的。我现在写一个数据处理 pipeline,或者设计一个推荐策略实验,用到的基本功仍然是当年刷题时打下的。

根据我个人经验,最后再分享一个心得:笔试前一周不要再疯狂刷难题了,把错题本翻一遍,把常用模板(快排、二分、KMP、拓扑排序、并查集)手写一遍,比什么都管用。考场上的你,拼的不是灵感,而是肌肉记忆和稳定的心态。祝准备秋招的各位顺利上岸。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 13:56:48

Gradio 3 行代码搭建模型界面:Colab 零成本部署演示 Demo

Gradio 3 行代码搭建模型界面&#xff1a;Colab 零成本部署演示 Demo 【免费下载链接】gradio Build and share delightful machine learning apps, all in Python. &#x1f31f; Star to support our work! 项目地址: https://gitcode.com/GitHub_Trending/gr/gradio …

作者头像 李华
网站建设 2026/8/31 13:56:45

MATLAB实现核偏最小二乘KPLS:从原理到代码的非线性建模指南

简介&#xff1a;本资源是面向机器学习与数据分析初学者及科研人员的MATLAB版核偏最小二乘&#xff08;KPLS&#xff09;算法实现包&#xff0c;专为解决高维、非线性回归与建模问题设计&#xff0c;适用于化工过程建模、光谱分析、生物信息等需强非线性拟合能力的场景。压缩包…

作者头像 李华
网站建设 2026/8/31 13:56:14

具身智能商业化:从“接工单”到“算ROI”的系统工程

在机器人赛道&#xff0c;最近两年有一个明显变化&#xff1a;很多团队不再只聊“我们的机器人能做什么动作”&#xff0c;而是开始聊“这个项目多久回本、一年能替客户省多少成本”。这背后不只是市场话术变了&#xff0c;而是具身智能的商业化逻辑正在从“接工单”切换到“算…

作者头像 李华
网站建设 2026/8/31 13:56:07

从画质到智能:探针评测如何评估视频生成模型的视觉理解能力

视频生成模型发展到现在&#xff0c;大家关注的焦点已经不是“它能生成多清晰的画面”&#xff0c;而是“它到底懂不懂自己在生成什么”。同样是让模型生成一段“猫从桌子跳下来”的视频&#xff0c;有的模型能给出流畅合理的运动过程&#xff0c;有的模型却会出现猫在空中翻跟…

作者头像 李华
网站建设 2026/8/31 13:53:04

SpringBoot+Vue教务管理系统:多端联动实战开发全解析

简介&#xff1a;这是一套面向教育培训机构的全栈教务管理解决方案&#xff0c;适用于Java后端、Vue前端及微信小程序开发者学习与二次开发&#xff0c;解决多校区协同、招生分销、直播教学等典型教育数字化场景中的系统集成难题。资源包共359个文件&#xff0c;含260个Java核心…

作者头像 李华
网站建设 2026/8/31 13:52:16

Libredwg Android交叉编译实践:从NDK配置到JNI集成

简介&#xff1a;本资源是面向Android平台开发者的LibreDWG交叉编译成品库&#xff0c;专为解决在Android Studio环境下手动编译LibreDWG时常见的环境配置复杂、架构兼容性差、编译报错频发等问题而提供。资源已预编译生成arm64-v8a、armeabi-v7a、x86、x86_64四大主流ABI的动态…

作者头像 李华