360春招笔试复盘:算法题型与解题思路全解析(含避坑指南)
发布时间:2026/9/1 22:14:03来源:尧图网络
又到一年春招季不少同学应该已经在牛客、力扣上刷了一圈题准备投360的春招。我是去年参加的第二批笔试当时做完之后整理了不少复盘笔记一直没来得及发出来。今天就把当时的原题考点、我的解题思路、还有踩过的坑一次性说清楚给接下来要上场的同学做个参考。这篇文章不涉及具体原题泄露只讲题型分布、解法思路和备考策略都是我基于考后回忆和同类题型整理的大家放心看。这次360的春招编程题整体风格偏实际应用不像某些厂爱出那种纯脑洞的数学题更看重基本功和边界处理能力。题型主要集中在线段树、动态规划、字符串处理、双指针这几个方向题目难度梯度设计得比较明显第一题基本送分最后一题才会真正拉开差距。1. 春招笔试的整体定位与考点分析1.1 360春招编程题的难度与风格定位笔试一共两批我参加的是第二批。整体感受是代码量不大但思路拐弯比较多尤其是中等题喜欢在经典算法上做变种比如把贪心藏在区间合并里把DP藏在一维数据里。对比牛客网上能搜到的历年360真题2023年的批次延续了几个固定风格第一题通常是模拟或简单字符串送分题考察读题仔细程度和基础代码速度第二题开始进入正题常考前缀和、双指针、滑动窗口这类优化思路第三题是中高难度线段树、树状数组、状态压缩DP出现频率较高压轴题往往是综合题可能在拓扑排序、并查集、DP加贪心的组合上做文章还有一个容易被忽略的点360的笔试环境用的是牛客网的在线OJ支持C、Java、Python等主流语言。这里要提醒一句能用C或Java的尽量别用Python。不是Python不行而是牛客的判题机对Python的递归深度和大量输入处理的性能压得比较狠同样的算法复杂度C一遍过Python可能卡在超时边缘。1.2 常考能力模型与备考优先级从题目反推考察的能力模型360比较看重下面这几项数组处理能力——不是简单的遍历而是在一次遍历中完成统计、计算、更新多个状态。比如前缀和配合哈希表就是高频套路。数据结构的熟练度——线段树和树状数组几乎成了360中等以上题目的标配。不是说让你背板子而是得理解单点修改、区间查询背后的更新逻辑。状态转移的建模能力——动态规划题通常不会给你明显的“选或不选”而是会包装成区间覆盖、任务分配、路径规划的样子。针对这个能力模型我建议备考优先级这样排双指针和滑动窗口 前缀和/差分 常见DP模型背包、LIS、区间DP 线段树/树状数组 图论基础拓扑、最短路、并查集。贪心算法不用专项准备前提是你把排序和数据结构弄熟了贪心策略通常就是排序加一次遍历的事。2. 核心题型逐题复盘与解题思路拆解2.1 字符串与哈希结合的前缀统计题第二批的第一道编程题考的是字符串前缀匹配加哈希统计。题面大致意思是给一组字符串要求统计有多少个字符串的前缀在另一组字符串中出现过。这类题属于典型的“看起来能暴力但其实必须优化”的类型。最直接的暴力解法就是两重循环对每个字符串枚举它的所有前缀再到目标集合里查。时间复杂度是O(n*m*len)n和m是字符串数量len是字符串平均长度。如果数据量小没问题但笔试数据一般会把暴力卡掉。正确姿势是用哈希集合存目标字符串的所有前缀然后遍历待匹配字符串判断它的前缀是否在集合里。代码很简单关键是一次性把某个字符串的所有前缀都生成出来存好而不是在匹配的时候逐个拼接。#include bits/stdc.h using namespace std; int main() { int n, m; cin n; vectorstring a(n); for (int i 0; i n; i) cin a[i]; cin m; vectorstring b(m); unordered_setstring prefix_set; for (int i 0; i m; i) { cin b[i]; string cur; for (char c : b[i]) { cur c; prefix_set.insert(cur); } } int ans 0; for (string s : a) { if (prefix_set.count(s)) ans; } cout ans endl; return 0; }这个解法的时间复杂度是O(总字符数)空间复杂度也是O(总字符数)。要注意的坑是前缀集合可能非常大如果字符串总长度是10^6量级用unordered_set是安全的但别用set红黑树插入和查找都有log n的常数很容易超时。2.2 区间合并与贪心结合的覆盖问题第二批第二题核心是区间覆盖。给若干个区间问最少需要保留多少个区间才能保证每个点至少被一个区间覆盖到。这个题本质上是经典的“最小区间覆盖”贪心模型只是题干换了一层皮。贪心策略是固定的按左端点排序维护当前覆盖的最右端点然后每次在左端点不超过当前右端点的所有区间里选右端点最大的那个。如果找不到下一个区间说明覆盖断裂直接返回-1。这里有个细节很关键排序是按左端点但每次贪心选的是右端点最大的区间。很多人卡在这一步想着按右端点排序也行其实不行。按左端点排序是为了保证扫描的单调性每次从起点往后找能接上的区间按右端点排序会破坏这个顺序导致覆盖出现空洞。#include bits/stdc.h using namespace std; int main() { int n, L, R; cin n L R; vectorpairint,int segs(n); for (int i 0; i n; i) cin segs[i].first segs[i].second; sort(segs.begin(), segs.end()); int cur L, idx 0, ans 0; while (cur R idx n) { int maxr cur; while (idx n segs[idx].first cur) { maxr max(maxr, segs[idx].second); idx; } if (maxr cur) break; // 没有能推进的区间 cur maxr; ans; } if (cur R) cout -1 endl; else cout ans endl; return 0; }这个题值得深入想一下为什么贪心在这里是对的因为在已经覆盖到的范围里往后延伸时选择右端点最大的区间一定不会比选择其他区间更差。如果你选了一个较小的右端点后续还要再选一个区间来补区间数量只会更多。这就是典型的“局部最优能推出全局最优”的证明思路。2.3 动态规划一维状态设计的经典考题第二批的第三题是典型的DP题。题面描述得比较绕但抽象之后本质是给定一个数组要求分成若干连续段每一段的代价定义为段内最大值减最小值求整体最小总代价。这个题刚读题的时候容易想复杂因为它不限分段数量只看总代价最小。如果你直接想贪心会发现无从下手因为每段的最值差受分段方式影响。正确的切入点是先想暴力DP再想优化。先定义状态dp[i]表示前i个元素被分成若干段之后的最小总代价。那么转移方程就是dp[i] min(dp[j] cost(j1, i))其中 j 从 0 到 i-1。cost(j1, i) 是子数组从第 j1 到第 i 个元素的最值差。这个转移是O(n^2)的n如果在10^3量级勉强能过但如果n是10^5必须优化。优化的思路是单调栈。因为 cost(j1, i) max(j1, i) - min(j1, i)我们可以分别维护两块贡献一部分是“以i结尾的某个区间最大值产生的贡献”另一部分是“最小值产生的贡献”。用单调栈维护区间最大值和最小值的变化配合线段树维护dp[j]加上当前最值差的最小值。这一步比较高级笔试现场能写出来的基本是冲满分的那批人。我建议如果时间紧先把O(n^2)的暴力DP写出来拿部分分。360的判分机制是按通过用例比例给分的暴力过掉60%到70%的用例性价比也很高。笔试不是竞赛不要求你必须拿满分拿到足够的分数进面试才是最终目标。2.4 数据结构的灵活运用树状数组求逆序数第二批的压轴题之一是逆序对变种要求统计每个元素与其左侧比它小的元素组成的逆序对数量之和。经典解法是用归并排序或树状数组但这里加了点变化不是数全局逆序对而是对每个位置统计以它作为较大元素的逆序对数量。其实用过树状数组的同学都知道这个套路非常成熟离散化之后从左往右扫描每遇到一个元素就查询树状数组里小于它的元素个数然后把这个元素插入。核心代码也就二十行但坑在离散化和数据范围。#include bits/stdc.h using namespace std; int lowbit(int x) { return x (-x); } void add(vectorint bit, int i, int v) { for (; i (int)bit.size(); i lowbit(i)) bit[i] v; } int query(vectorint bit, int i) { int res 0; for (; i 0; i - lowbit(i)) res bit[i]; return res; } int main() { int n; cin n; vectorint a(n); vectorint b(n); for (int i 0; i n; i) { cin a[i]; b[i] a[i]; } sort(b.begin(), b.end()); b.erase(unique(b.begin(), b.end()), b.end()); vectorint bit(b.size() 1, 0); long long ans 0; for (int i 0; i n; i) { int id lower_bound(b.begin(), b.end(), a[i]) - b.begin() 1; ans query(bit, id - 1); add(bit, id, 1); } cout ans endl; return 0; }有一个不少新手会犯的错误是忘记离散化直接把十万甚至百万量级的数值当数组下标用结果就是越界或者爆内存。遇到大数据范围先离散化这是树状数组题目的基本动作。3. 实操过程笔试现场的做题节奏与试错记录3.1 时间分配与做题策略实战的时候时间管理比刷题量更重要。360笔试总共90分钟两道到四道编程题不等批次不同题量不同第二批实际是四道题。我当时的分配策略是前20分钟通读全部四道题把每道题的数据范围、时间限制、题面关键词标出来。第一题直接开写趁脑子还清醒。20到45分钟主攻第二题和第三题。边写边验证样例能跑通样例就立刻提交先拿到分数。45到75分钟做第四题也就是最难的压轴题。写个暴力版本保底然后尝试优化。最后15分钟检查输入输出格式、边界情况、有没有漏掉多组测试数据的情况。这个节奏的实际好处是不会出现最后一题没时间看而空着的情况。因为最后一题即使拿不到全部用例的分数暴力版本也能覆盖一部分。3.2 现场翻车的三个真实案例我复盘自己当时和周围同学的做法总结了三个典型的翻车场景第一个是第一题就被卡住。第一题其实是送分题但因为前面说的字符串前缀统计有的同学上来没仔细读题把“前缀在目标集合中出现过”理解成了“完全匹配”结果样例过了提交后只对了一半用例。这种问题纯属读题不仔细没有别的解释。我的习惯是读完题先把样例在草稿纸上手动推一遍确认自己的理解跟样例输出完全吻合再动手写代码。第二个是第二题忘了排序。区间覆盖问题排序是整个算法的第一步但有些同学一旦进入写代码状态就急着写主逻辑把排序漏了。漏排序之后样例不一定会挂因为样例里的区间可能恰好有序但大数据用例一定挂。这个坑的教训是涉及区间的问题先问自己“排序了没有”。第三个是第三题状态定义错误。我前面提到的DP题有的同学把dp[i]定义成了“前i个元素分成k段的最小代价”结果发现题目根本不要求分段数量白白多写一维时间复杂度直接爆掉。这不是能力问题是做题习惯问题。写完转移方程之前先画一画状态的含义确认它只依赖前一个状态或者更早的几个状态不要盲目加维度。3.3 从暴力到满分的优化路径以第三题的DP为例展示一下我在现场从暴力到优化的实操过程。第一步先把O(n^2)的暴力写出来验证算法的正确性。转移是dp[0] 0 for i in 1..n: mx -INF mn INF for j in i-1 down to 0: mx max(mx, a[j1]) mn min(mn, a[j1]) dp[i] min(dp[i], dp[j] mx - mn)注意内层从i-1倒着往前扫因为这样mx和mn可以O(1)维护不需要额外开二维数组存区间的最值。第二步观察这个转移的本质dp[j] max(j1,i) - min(j1,i)。我们能拆成两部分左半部分 dp[j] - min(j1,i)这部分对某个固定i来说随着j变化min值呈现单调递减的阶梯状可以用单调栈维护等价区间右半部分 max(j1,i)的贡献同理用另一个单调栈维护然后用线段树维护每个j对应的候选值查询区间最小值整体复杂度降到O(n log n)。这个优化需要比较扎实的线段树功底但它的原理值得反复咀嚼。单调栈在这里的作用是“把连续的一段j合并成同一个值”当加入的新元素比栈顶元素大时它会更新一段区间的最大值我们只需要在线段树上对这段区间做区间更新。这是经典的“单调栈线段树优化DP”套路力扣上有好几道题都用到了。4. 常见问题排查与避坑技巧实录4.1 输入输出处理的隐藏陷阱笔试界面用的是牛客OJ输入方式跟力扣不同不是给你封装好的函数而是让你从标准输入读取数据。这块如果处理不好前面所有努力都白搭。最常见的问题是多组数据。有些题目会写“输入包含多组测试数据每组占一行”这意味你需要用while(cin n)这样的循环把每一组都处理掉而不是只处理一次。如果你只处理了一组数据那可能第一个用例输出正确但从第二组开始全部错误。另一个坑是数组下标越界。特别是当数据范围标注是“10^5”时别真的开一个大小为10^5的数组备用应该根据输入n实际分配空间。我在做树状数组那题时一开始开了一个固定大小的全局数组结果在本地测试没问题提交后却被判段错误就是因为某个测试数据里n比预设值大。稳妥的做法是用vector动态分配。4.2 时间复杂度预估与超时预防笔试中经常出现“本地秒出结果提交却超时”的情况。一个实用的预估方法是1秒大概能执行3×10^8次简单运算但如果你用了map、set、vector的拷贝、递归等操作实际吞吐量要低一个数量级。我给自己定了一条线看到n是10^5就用O(n log n)看到n是10^4O(n^2)可以承受看到n是10^6基本只能O(n)或O(n log n)极简实现。数据范围直接在题面上写着动笔之前扫一眼心里就有底了。关于超时还有一个容易被忽视的点循环里别再嵌套字符串拼接。比如那题字符串前缀统计如果你在循环里用cur c这没问题因为每个字符只操作一次但如果你写成cur s.substr(0, k)每生成一个前缀就是O(len)的拷贝总复杂度直接升到O(n^3)必超时。这也是为什么我用累加方式生成前缀而不截取。4.3 笔试环境的预备动作过了笔试不意味着万事大吉我到面试阶段还被问到了笔试时的一个优化思路。所以建议笔试结束后立刻把每道题的解法记录到自己的笔记里特别是当时没做出来的题回去后花时间补完。360的面试官可能会直接让你讲笔试题的思路如果你能说出从暴力到优化的完整演进会是明显的加分项。再分享一个实用的备考工具组合牛客网刷题时选“公司真题”分类里的360卷同时配合力扣的“前缀和”“滑动窗口”“区间DP”标签专题刷。前者用来适应笔试环境后者用来补算法盲区。我去年秋招前主要就是刷这两个效果比买课好。5. 我摔过跤之后总结的刷题方法论说实话去年第一次准备360笔试的时候我走了一段弯路。当时只顾着刷力扣的热题100心里想着“热门题刷八九百道笔试肯定没问题”。结果上了考场才发现力扣热题更多的是单知识点深度考察而360的笔试比较看重知识点的组合运用。区间覆盖这道题本身考察了贪心加排序单看每个知识点都不难但组合起来就会刷掉一批只会背模板的同学。后来我调整了复习策略现在回头看觉得这套思路值得分享给正在准备春招的朋友第一按题型专项突破而不是按难度梯度刷题。把同一种套路的不同变种放在一起集中刷比如连续一周只看滑动窗口的题把“固定窗口”、“非固定窗口”、“带数据结构维护的窗口”全过一遍。这样在考场上看到题干你会第一时间识别出题人想考什么套路而不是站在一个知识点门口反复徘徊。第二每道题都要做复杂度分析。这不是让你在草稿纸上精确推导而是养成“看一眼数据范围就锁定算法复杂度的直觉”。连5分钟都花不到但能让你在大方向上不跑偏。第三一定要模拟真实考场环境。至少提前一周把所有练习都放到牛客的在线编辑器里做关闭本地IDE的自动补全和语法提示。说实话习惯了IDE的自动补全之后突然切换到OJ的裸编辑器写代码速度会下降至少三成。提前在OJ环境里练手感可以有效避免考场上因为“写不惯”而浪费时间。第四做完题后一定要复盘。复盘不只是把题解看懂而是要把这道题跟以前做过的题做类比抽象出共同的模式。比如前面说到的“单调栈线段树优化DP”如果你做过“修剪草坪”那道题就会发现它们底层是同一个套路。抽象提炼出来的模式才是你真正掌握的东西。这些话看起来像是老生常谈但笔试场上真正能稳定执行的并不多。我第二次做类似的题目时因为有了复盘形成的模板十分钟就写出了正确答案。这种手感不是靠临时抱佛脚能速成的一定是从日常刷题中沉淀下来的。6. 针对不同基础人群的备考建议说一下不同水平阶段的针对性打法。如果你还有大约两周时间现在才开始准备那么心态和策略比盲目刷题重要得多。基础偏薄的同学算法题目前还处于靠暴力过样例阶段先把“拿基础分”作为核心目标。这个阶段请把重心放在第一、第二题的送分题级别上数组操作、字符串处理、简单模拟、基础双指针。刷题时不要怕简单能五分钟内完整AC一道简单题比苦思冥想一道难题三小时有价值得多。具体操作建议每天固定做十道简单题加两道中等题简单题练熟练度中等题练思维拓展。遇到做不出来的题直接看题解看懂之后合上题解自己重写一遍。两道中等题里面只要有一道能独立AC就已经很了不起了。别贪多这个阶段的目标是看见题目就有思路写代码不卡壳。基础尚可的同学算法入门已过经典题型掌握七成这个阶段的目标从“会做”转变成“做得快、做得稳”。建议每天做四道中等难度题加一道困难题重点刷360常考的区间覆盖、前缀和、DP优化、树状数组这四个方向。每道题限时25分钟到时间没做出来就标记一下看题解然后第二天重做。这个阶段特别建议做的事是把你的解题过程录屏幕或者写成文字。不用发出去自己复盘就好。你会惊讶地发现很多“我看懂了但写不出来”的题其实卡在中间某一步的代码实现上比如区间更新时边界写错。定位出自己的薄弱环节比多刷十道题还有用。基础扎实的同学难题已过关竞赛经验丰富这个阶段大概率不是怕题不会做而是怕阴沟里翻船。建议把重心放在细节和稳定性上特别是边界条件、特殊用例空数组、单元素、全相等、极大极小值、数据类型溢出这三大类。笔试翻车往往不是栽在难题上而是栽在简单题的边界条件上。此外如果有余力建议关注一下360的产品线和技术栈了解他们可能在什么业务场景下出题。比如360做安全、搜索、浏览器等业务那么字符串匹配、日志分析、用户行为序列这类问题就有可能出现。提前了解业务背景能在考场上更快理解题干的现实含义。最后再说一句笔试不是终点它就是一次普通的在线考试。发挥失常了还有下一批不用太有心理负担。真正拉开差距的不是某一次考试的成绩而是你是不是每次都从考试里学到了一点点东西然后在下一次用上。祝各位好运有问题欢迎在评论区交流。
网站建设高端定制企业官网