ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

智加科技2023校招编程题解析:高频题型与解题攻略

智加科技2023校招编程题解析:高频题型与解题攻略 智加科技2023校招技术岗的编程题整体做下来最明显的感觉是题目本身没有特别偏难怪但它习惯把算法题藏到卡车调度、传感器数据处理、车队编组这样的业务场景里比单纯在LeetCode上刷题多了一层“读题建模”的考验。我去年秋招准备了大概三周把能搜集到的智加笔试题按题型做了归类这里统一整理出来每道题都附上思路推导、复杂度分析和参考代码应该对接下来投智加算法岗或者后端岗的同学有直接帮助。需要先说明一点校招笔试题目不同批次会有变化我整理的是2023年几轮笔试里高频出现的题型并不保证和某一场完全一致。但算法题的核心考点相对固定把这几类吃透再配合官网岗位要求做针对性准备就比盲目刷题要稳得多。下面先聊智加笔试的出题风格再逐题拆解最后把现场答题和避坑经验一并写出来。1. 智加的编程题考什么能力模型和出题风格1.1 从岗位画像看考核目标智加科技做的是自动驾驶卡车业务链涵盖感知、定位、规划控制、车载系统和车队调度平台不同方向的技术栈差异很大。但无论投哪个技术岗笔试都逃不开算法基础题。这背后的逻辑是校招新人进来后大概率需要直接接触海量传感器数据、路径规划、车辆调度等模块这些模块的核心底层能力就是数据结构与算法。面试官希望用编程题筛出两类人——一类是算法基本功扎实的另一类是能把场景问题抽象成算法模型的。后一点在智加的笔试里体现得特别明显。比如同样考滑动窗口它不会直接给你一个数组让你求最短子数组而是说“高速路上N辆卡车经过路侧设备记录下它们的ID序列请你找出一个最短时间段让这段时间里所有不同ID的卡车都至少出现过一次”。如果你只背了模板、不擅长从业务描述里提取“连续子数组”“不同元素种类”这些关键词第一关就会卡住。另外智加的编程题对数据规模和边界条件的考察也很多。题目会把数组长度放到10的5次方甚至更高这时候O(n^2)暴力解法一定超时逼着你优化到O(n log n)或O(n)。这其实非常贴近工程实际——自动驾驶系统在线处理数据时性能和实时性是硬指标。所以准备智加笔试不能只满足于“能跑对样例”还要养成每道题先看数据范围、再评估复杂度的习惯。1.2 2023年题型分布与难度分层从2023年秋招的反馈来看智加技术岗笔试的编程题通常是2道后面跟着十几道选择题。选择题主要覆盖C语言特性、数据结构复杂度、操作系统、网络基础以及少量机器学习基础算法岗更明显。编程题难度大致可以分为两个梯队第一梯队是中等偏易的题核心考点集中在滑动窗口、前缀和、哈希表、简单动态规划。这类题只要你系统刷过LeetCode热题100基本可以在15到25分钟内稳拿。第二梯队是中等偏难的题常见的是拓扑排序、带权最短路、状态压缩动态规划、线段树这类需要现场推导的题型。它不会考到竞赛难度但如果你只刷过简单题面对这类题时会因为不熟悉套路而无从下手。值得注意的一点是编程题的评分往往不仅看最终答案正确与否部分平台会按测试用例通过率给分。这意味着即使你写不出最优解先用暴力解法拿部分分也很有意义。我见过不少同学因为某一道题卡住就整场放弃其实这是最亏的。后面我会详细讲答题时的策略这里先记住一句话笔试的目标是在有限时间内拿最多的分不是追求每一题都完美解出。2. 四类高频题型的完整拆解与参考实现2.1 滑动窗口最短覆盖区间问题原题场景大致是这样的一段高速上架设了若干路侧识别设备按时间顺序记录经过车辆的ID。给定一个长度为N的数组数组元素是车辆IDID范围为1到10^5。现在要求一个最短的连续子数组长度使得子数组中包含整个数组中所有不同的ID。如果不存在这样的子数组返回0。这道题考的是滑动窗口和哈希表两个高频点解法模板非常标准但很多人第一次看到会想到暴力枚举所有子数组复杂度O(n^2)在N10^5的范围内一定超时。正确思路是维护一个左指针和一个右指针右指针不断向右扩展窗口把新元素加入哈希表计数当窗口内已包含所有不同ID时尝试收缩左指针收缩过程中不断更新最小窗口长度。参考实现如下def shortest_covering_subarray(cars: list[int]) - int: n len(cars) total_kind len(set(cars)) if total_kind 0: return 0 cnt {} left 0 ans n 1 for right, c in enumerate(cars): cnt[c] cnt.get(c, 0) 1 while len(cnt) total_kind: ans min(ans, right - left 1) cnt[cars[left]] - 1 if cnt[cars[left]] 0: del cnt[cars[left]] left 1 return ans if ans n else 0每个元素最多进窗口一次、出窗口一次所以整体时间复杂度是O(n)空间复杂度O(k)k为不同ID的种数最坏情况下也是O(n)。这个题要特别注意收缩窗口的时机——一定是“窗口已包含所有不同ID”时才能收缩而不是窗口长度大于某个阈值时。很多人写成固定窗口大小那就不对了。这道题对应LeetCode第76题和第3题的思路本质都是“满足条件的最短/最长子串”。准备智加笔试时建议把这两道题连在一起刷重点体会left指针的移动逻辑什么时候收缩、收缩之后如何恢复计数、什么时候更新答案。这几个细节想清楚了类似题基本都能套上。2.2 动态规划载重限制下的最大装载价值原题场景是一辆自动驾驶卡车有载重上限M仓库里有N批货物每批货物有重量w[i]和价值v[i]每批货物要么整批装车、要么不装不能拆开。问在不超过载重上限的前提下能装走的最大总价值是多少。如果只看场景描述这就是一个标准的01背包问题。数据范围通常是N不超过500M不超过10000所以用动态规划的复杂度O(N*M)在可接受范围内。定义dp[j]表示载重为j时能获得的最大价值初始值全部为0然后遍历每批货物对载重j从M到w[i]逆序更新def max_load_value(n: int, m: int, weights: list[int], values: list[int]) - int: dp [0] * (m 1) for i in range(n): for j in range(m, weights[i] - 1, -1): dp[j] max(dp[j], dp[j - weights[i]] values[i]) return dp[m]这里有个关键点很多人容易忽略内层循环为什么必须从大到小遍历因为dp[j]在更新时依赖的是dp[j - w[i]]而这个值一旦在本轮中被提前更新就会导致同一批货物被重复装入退化成完全背包问题。为了避免这种情况必须让j从大到小走保证dp[j - w[i]]仍然是上一轮的状态。时间复杂度O(N*M)当N500、M10000时大约是500万次操作用Python跑也很快不会超时。空间上可以优化到O(M)也就是上面代码用的滚动一维数组。如果题目改成每批货物可以拆装或者可以装多件那就是完全背包或分组背包的变体别套错模板。实际上智加这类题目给出的“货物价值”有时会包装成“运输收益”或“任务报酬”但解题模型完全一致。建议把01背包、完全背包、多重背包三种模板都过一遍尤其是01背包的状态转移方程一定要能默写出来并且解释清楚逆序的原因这在后面的面试环节极大概率会被追问。2.3 图论车队依赖关系与启动顺序这道题属于第二梯队出现的频率不低。场景是一个自动驾驶卡车编队里有N辆车编号0到N-1某些车必须在另一些车之后才能启动比如后车需要接收前车的心跳信号才能初始化。给定M条依赖关系每条关系用(a, b)表示a车必须在b车之前启动求一个合法的启动顺序。如果存在多个合法顺序要求输出字典序最小的那个。依赖关系明显是有向图模型合法的启动顺序就是拓扑排序序列。普通的拓扑排序用队列维护入度为0的节点得到的是任意一个合法序列不保证字典序最小。要输出字典序最小的拓扑序列只需要把普通队列换成小顶堆优先队列每次取当前入度为0的编号最小的节点import heapq def start_order(n: int, edges: list[tuple[int, int]]) - list[int]: graph [[] for _ in range(n)] indeg [0] * n for a, b in edges: graph[a].append(b) indeg[b] 1 heap [i for i in range(n) if indeg[i] 0] heapq.heapify(heap) res [] while heap: u heapq.heappop(heap) res.append(u) for v in graph[u]: indeg[v] - 1 if indeg[v] 0: heapq.heappush(heap, v) return res if len(res) n else []返回结果如果长度不等于N说明图中存在环编队里存在循环依赖这种情况应该向调用方返回一个空列表或者明确报错。笔试时很多人会忘记判断这一条直接返回res如果测试用例里包含环就会少过一个用例。这个题的考点拆成两块看一是能不能识别出“启动依赖”就是有向无环图上的拓扑序二是知不知道用堆来保证字典序最小。只答出拓扑排序不够题目明确要求字典序最小队列方案就会挂掉一半测试点。如果后续面试官追问大概率会问“如何判断是否存在环”和“复杂度是多少”。建图是O(NM)堆操作每次O(log N)整体O(N log N M)。这道题和LeetCode第210题“课程表II”几乎同源区别就是智加要求字典序最小把BFS队列换成堆代码量稍大一点但思路是通的。2.4 前缀和与同余统计可被K整除的子数组原题是一个整数数组统计有多少个连续子数组的元素之和能被K整除。数组长度可以达到10^5K也很大暴力枚举所有子数组O(n^3)或者用前缀和O(n^2)都不现实得用同余定理优化到O(n)。核心结论如果前缀和pre[i]和pre[j]对K取模的余数相同那么子数组(i1, j)的和一定可以被K整除。所以遍历数组时维护一个哈希表记录每个余数出现的次数每次遇到一个新余数r就把之前已经出现过的次数累加到答案里然后再更新计数def count_divisible_subarrays(arr: list[int], k: int) - int: cnt {0: 1} prefix_sum 0 ans 0 for x in arr: prefix_sum x r prefix_sum % k ans cnt.get(r, 0) cnt[r] cnt.get(r, 0) 1 return ans这里有一点要特别提醒如果笔试时用的语言是C或者Java负数的取模结果可能和我们数学上理解的余数不一致。比如在C里-5 % 3结果是-2而Python里结果是1。为了让余数统一到非负区间代码里最好写((prefix_sum % k) k) % k。如果直接在哈希表里存负数余数很可能导致前后两次计算不匹配测试用例一多就容易漏。这道题对应LeetCode第560题和第974题属于“前缀和哈希表”的经典套路。它的变形还包括求“和等于K的子数组个数”“和最接近0的子数组”等。智加把这类题放在第一梯队或第二梯队的边缘是因为它考察的不仅是前缀和知识还有对取模边界条件的敏感性。很多人在笔试时能写出主体逻辑却在负数取模上翻车实在可惜。3. 笔试现场全流程复盘与答题策略3.1 从投递简历到笔试关键时间线智加科技的校招一般分提前批和正式批。提前批通常在6月底、7月初开启流程更短有些方向甚至能免笔试直接进入面试正式批在8月底到9月中旬陆续开放。建议大家不要等正式批尽量赶提前批因为hc更多面试官也有更充足的时间和你深聊。简历投递后一般一到两周内会收到笔试邀请。如果一直没有消息可以留意一下邮箱的垃圾箱我身边就有同学把笔试通知当成垃圾邮件错过了。笔试一般安排在某个工作日晚上的固定时段时长90分钟使用牛客网或赛码平台。提前半天检查好网络、摄像头和麦克风很多平台有在线监考功能中途换浏览器或者切窗口会被记录严重时直接判定违规。需要特别强调的是笔试通知里的岗位信息一定要看清。智加有算法岗、后端开发岗、嵌入式岗等不同方向虽然编程题部分共用题库但选择题的侧重差别很大。算法岗会多几道机器学习和概率统计嵌入式岗会多问操作系统和内存管理。考前花十分钟到官网看一遍目标岗位的职责描述比自己盲目刷题高效得多。3.2 90分钟的时间分配建议我个人的习惯是先快速浏览全部题目再按“性价比”排序做题。选择题大概10到15道每题1到2分知识点很杂但不该花太多时间纠结。编程题两道一道中低档、一道中高档分值占比高是笔试的决胜盘。推荐的时间分配是前10分钟通读试卷并快速做完有把握的选择题然后花25分钟左右完成第一道编程题花35到40分钟攻第二道编程题。最后剩余时间用来补漏和检查。如果第二道题卡了超过20分钟还没思路先停手回头把第一道题的所有边界测试用例再跑一遍或者把选择题没把握的题再想想避免捡芝麻丢西瓜。特别注意多数在线笔试平台支持本地IDE调试后再粘贴提交但也有一些平台只能在线编辑。开考第一件事先花30秒确认输入输出格式和可用的语言环境。有一部分平台预置了main函数的输入解析模板直接在上面改就行别自己另起炉灶重写输入解析反而容易踩多组样例的坑。3.3 接到一道编程题后的五个关键步骤第一步把业务场景还原成算法模型。读完题先不急着写代码而是问自己三个问题数据是什么结构的要求的最优目标是什么有没有明显的约束条件比如“求一个时间段覆盖所有卡车ID”本质上就是求最短连续子数组一看到“依赖关系、启动顺序”马上联想到有向图和拓扑排序。第二步计算暴力解法的复杂度判断能不能直接暴力。如果N是100以内暴力往往可行如果N到了10^5就该思考滑动窗口、前缀和、二分、堆这些优化手段。第三步先写一个能跑出正确答案的朴素版本再优化。这是我在笔试里最推荐的做法。哪怕朴素版只能过一半测试点也比空着强。只要时间允许再把朴素版改成线性或O(n log n)版本。第四步写关键代码时把变量名起得清楚一点。笔试代码在面试环节会被面试官翻出来看如果全是a、b、c这种临时变量你自己过两天都看不懂更别说讲给面试官了。用left、right、prefix_sum、cnt这类语义化命名既方便自己调试也方便后续复盘。第五步边界测试一定要做。每一道题都至少跑一遍空输入、单元素输入、最大数据规模输入。滑窗类的题重点看窗口收缩时机DP类题重点看初值图论类题重点看环和孤立节点。这几分钟不会白花。4. 常见问题与避坑指南4.1 高频失分点前五名根据我和身边同学的经验智加笔试翻车最多的是下面五个点。输入输出格式写错。在线笔试平台的输入输出判分非常严格多余的空格、换行、提示字符都会导致Wrong Answer。建议完全按照题目给出的示例格式来不要自己加任何print提示。尤其是C选手如果数据量大用cin.tie(nullptr)和ios::sync_with_stdio(false)加速否则可能因为IO超时丢分。不读数据范围直接写最暴力的解法。智加的笔试题目会把N给到10^5以上很多暴力解法在示例用例上表现正常但提交后大面积超时。准备阶段就要养成习惯读题时先看数据范围在心里把复杂度的上界框出来。递归深度不够。用Python写DFS类题目时如果递归深度超过默认的1000层会直接报RecursionError。处理图论中的深搜或树的遍历时要么设置sys.setrecursionlimit(1000000)要么干脆改用迭代栈或BFS避免在考场上手忙脚乱。忽略返回值类型和空数组。不少题目要求返回0或空列表有人却返回None或-1。尤其是上一个小节那道判断环的拓扑排序题遇到环应该返回空列表很多同学返回的是部分序列导致最终判定错误。对取模边界条件不敏感。比如上一小节的能被K整除问题C的负数取模会让结果偏一个符号。这种问题在样例测试里不一定暴露但测试用例一大随机性数据就会把你打回原形。写任何和取模相关的代码都先想清楚负数怎么办。4.2 笔试后的复盘与面试衔接笔试结束不等于这件事就过去了。我的经验是趁题目还在脑子里立刻把每道题的题意、自己当时的解法和卡住的点记下来。不用写太长记成关键词就行比如“第一题滑动窗口第二题拓扑排序最小堆卡在环的判断”。这些信息不仅用于复盘更可能在面试时被直接问到。智加的技术面试环节面试官大概率会打开你的笔试代码让你现场讲解思路或者针对某个细节追问“为什么这里用堆不用队列”“如果数据范围扩大十倍你怎么办”。这时候如果你笔试结束后认真复盘过就等于是把面试题提前准备好了。我在面试时就被问过“第二道拓扑排序题如果要求输出所有方案呢”当时因为复盘时想过这个扩展答得很顺畅。复盘时还有一个容易被忽略的动作把笔试时写的代码用本地IDE重新跑一遍补上边界测试用例并尽可能优化一遍。优化前后对比一下时间复杂度和运行时长这会让你对每道题的复杂度有更具体的感知。长此以往笔试里遇到同类题大概率一眼就能给出比较优的方案。5. 备考建议与个人心得5.1 按智加风格刷题的重点清单如果时间紧张建议优先把这几个题型刷到“条件反射”的程度数组与哈希、滑动窗口、前缀和与同余、01背包、拓扑排序、Dijkstra最短路、单调栈。它们在智加的笔试和面试手撕代码环节出现的频率最高。对应LeetCode可以这样刷第3题和第76题练滑动窗口第560题和第974题练前缀和第207题和第210题练拓扑排序第743题练Dijkstra第300题练动态规划里的LIS第739题练单调栈。每道题刷完不要只记题解把解题模板和复杂度分析写进自己的笔记隔一周再重写一遍。关于语言选择我的建议是至少在Python和C之间做到“一精通、一能写”。Python写算法题快适合在笔试中快速验证思路C在运行速度上有天然优势遇到数据规模极大的题目会更稳。我个人的策略是笔试时用C提交遇到思路不清晰的题目先用Python在本地快速验证逻辑验证通过后再翻译成C。这个习惯帮我避免了好几次因为语法错误浪费时间的尴尬。5.2 我实际踩过的坑和想提醒你的话三年校招笔试下来踩过的坑实在不少。最让我印象深刻的一次是某场笔试的拓扑排序题我用Python的递归写了DFS版本结果因为依赖链条太长直接爆栈后来又因为没判断环而只拿了部分分。当时明明知道有BFS堆的做法却因为慌乱没有第一时间想清楚白白浪费了大半场时间。现在回头看办法其实很简单考前把高频算法模板背到肌肉记忆遇到疑似图论的题先写BFS不会错。还想提醒一点笔试过程中如果连续两道选择题都不会不要慌。选择题分值占比有限真正的压舱石是两道编程题。稳住心态把编程题拿下笔试通过率就很有保障。我见过太多人选择题纠结太久最后编程题没时间直接整场崩盘。这篇文章到这儿基本把智加2023校招技术岗编程题的高频考点、解题模板和考场策略都讲完了。对我自己来说准备智加笔试的这段经历最大的收获不是背了多少题而是养成了拿到任何问题先分析数据范围和复杂度的习惯。希望后面准备校招的同学也能从这套题里找到自己的节奏少走几个我当时走过的弯路。
返回列表