OPPO研发岗笔试复盘:题型难度、ACM模式避坑与刷题策略
2026/8/30 20:38:55 网站建设 项目流程

2024年秋招OPPO研发岗笔试,我正好赶上第一批,三个编程题,90分钟,牛客在线笔试,ACM模式。先说结论:这套笔试题难度分布大概是简单、中等、较难,和主流大厂风格一致,真正的分水岭不在压轴题能写多少,而在中等题能不能稳拿、简单题能不能全对、压轴题能不能用暴力抢到部分分。这篇文章不是“透题”,而是把我完整走了一遍之后总结出来的题型逻辑、时间分配策略、常见的坑和复盘方法整理出来,给后面要上场的同学做一个参考。

不管你是准备投OPPO的Java岗、C++岗还是算法岗,只要笔试环节是编程题,核心逻辑都是相通的:数据处理能力、常见算法模板熟练度、边界意识、现场调试能力。这四点里任何一点有短板,笔试现场都会还回来。

1. 笔试基本盘:系统、题型与时间节奏

1.1 笔试系统和规则

OPPO研发岗的笔试用的是牛客网的系统,这是我最早想提醒的地方:不是IDE里写个函数返回结果就行,而是完整地读输入、算结果、打印输出。很多人刷LeetCode习惯只写核心函数,一到笔试就被输入解析卡住,特别是字符串和多组数据处理的场景,心态直接崩。

从实际体验来看,每套试卷是3道编程题,限时90分钟。语言随便用,C++、Java、Python、Go都行。我推荐用自己最顺手的语言,不要想着“哪道题适合哪个语言”再切换,笔试现场没有时间给你切换思维模式。

摄像头要开,浏览器会锁定屏幕,不能查资料。这个其实不算严苛,但确实有一些同学习惯性想开本地文档看模板,会被系统提示甚至警告,所以最好提前把所有常用模板记牢,不要指望现场翻。

还有一点:本地有IDE可以开,我建议用本地IDE写代码,调通后粘贴到在线编辑器里跑。牛客那个在线编辑器补全能力很弱,写起来效率低。我一般是本地VS Code写,测样例过了再粘过去,这样效率稳一些。

1.2 题型难度分布与时间规划

这三道题的难度曲线大致是这样:

题号难度建议用时常见考察点
第一题简单10-15分钟数组、字符串、模拟
第二题中等25-35分钟贪心、二分、前缀和、排序
第三题较难剩余时间DP、图论、数据结构优化

我把90分钟大致切成了:前5分钟通读三道题,判断每道题的题型难度,然后先做第一题,再做第二题,第三题放在最后处理。这套策略看起来平平无奇,但实际能避免一个很常见的问题:在第三题上死磕了40分钟,结果第一题因为赶时间写出一个小bug,第二题完全没时间思考,最后只过了一道半。

先说通读题目这一步,很多人跳过,直接上手写第一题。但通读绝对值得花这5分钟,因为你可以提前发现第三题到底是不是纯硬核难题,还是说只是看起来复杂、实际上能拆成中等题。如果第三题是“看着难但能得分”的题,你可以提前调整时间预算。如果第三题一眼看去就是数据结构优化那种,那就做好“暴力拿部分分”的心理准备。

实操下来,这个节奏能保证你在前两题上不失误,第三题有剩余时间薅分,整体拿到的分数会明显高于平均线。

2. 三道编程题逐个拆解:出题逻辑和做题思路

2.1 第一题:签到题怎么做到万无一失

第一题一般是整套试卷的“定心丸”,考的就是基础模拟能力。我这次遇到的是字符串处理类的题目,给了一堆输入条件,要求输出符合条件的统计结果。这类题没有算法层面的门槛,唯一的目标就是快速、准确地写出来。

但快速并不等于直接上手敲键盘。我建议哪怕第一题看起来再简单,也要先确认三点:数据范围是多少、有没有多组输入、输出格式是不是每一行一个结果。尤其输出格式,很多同学自测样例没问题,提交上去0分,结果发现是多了一个空格或者少了一个换行。

第一题还有一个隐藏考点:代码风格。虽然笔试没有人工看代码,但你自己在写第一题的时候,最好用函数把核心逻辑封装起来,而不是全塞在main函数里。这不只是为了“好看”,是因为很多时候你在题目里会漏掉某种输入情况,封装成函数之后,调试时可以单独写几个测试用例来验证,定位问题比线性代码快得多。

我的习惯是,第一题写完先不急着提交,花两分钟构造三个额外用例:最小数据规模、最大数据规模、边界重复输入。这三类用例过了,第一题基本就稳了。

2.2 第二题:中等题就是笔试的分水岭

第二题才是真正拉开差距的地方。这次遇到的中等题思路是“排序后贪心”,本质上是一个区间选择的变体。题目描述包装得很复杂,什么任务调度、资源分配之类的,但如果你能识别出“每个区间最多覆盖一次”或者“选择尽量多的区间”这种模型,就能立刻映射到经典贪心题。

怎么快速识别题目背后的模型?我的做法是看完题目之后,先不着急想解法,而是把题目的核心约束提取出来:是求最大还是最小,是判断存在性还是求方案数,数据范围是10^5还是10^9。这几个要素确认之后,解题方向基本就锁定了。

比如看到n在10^5级别,O(n^2)直接排除,考虑O(n log n)的排序加扫描,或是O(n)的前缀和、双指针。看到10^9,大概率是数学规律或者二分答案。这一层判断做得好,笔试效率会提升一个档次。

第二题最容易犯的错误是“直接上手套模板”。我知道很多人刷过很多题,看到“区间”两个字就写贪心,看到“分组”就写回溯。但这次第二题如果直接套典型模板,有一半的测试用例会挂掉,因为题目加了一个限制条件:每次操作会增加一个全局代价。这个条件让原来看似经典的贪心问题变成了需要额外维护状态的问题。所以套模板可以,但一定要在套模板之前,重新审视一下有没有新增的约束条件。

这道题我写完后也发现一个细节:如果不需要输出具体方案,只要最小值,那不用存全部状态,边遍历边更新就够,省内存也省时间。类似的优化在笔试里很吃香,因为它直接降低了代码出错的风险。

2.3 第三题:压轴题的“暴力拿分”哲学

第三题我看到题面的时候就知道自己未必能写正解。题目涉及树结构,要求在树上做路径聚合查询,数据范围是10^5,正常情况下正解应该是树链剖分或者树上差分。这类数据结构题在笔试里属于豪强题,确实能拉开分差,但对我来说,拿到部分分更重要。

第三题的策略我称之为“暴力拿分哲学”:先看数据范围里有没有小规模子任务,然后把暴力写法写出来,保证小数据能过,中等数据碰运气,大数据直接放弃。很多在线评测系统是分组给分的,你过了几个测试点就能拿几个测试点的分,所以空着绝对是最亏的。

具体到这道题,我用的是最朴素的DFS:每次查询遍历路径上的所有节点。时间复杂度接近O(nq),只能过非常小的数据。但没关系,笔试不是竞赛,能拿到的分数都是实打实的。

如果你有时间,可以在暴力版本上加一个小优化:预处理所有节点的深度和父节点信息,这样可以在求路径的时候做简单加速。但这属于锦上添花,核心还是先把暴力写对。这里有一个很现实的经验:暴力题最怕不是超时,而是写得不小心导致连小数据都过不了。所以暴力代码也别太随意,逻辑要清晰,变量名要能看懂,方便你检查。

3. 实战中的坑与排查经验

3.1 ACM模式下的输入输出陷阱

这是整套笔试里最容易翻车的地方,没有之一。我第一道题做完自测时发现,本地跑得好好的,放到牛客上就是输出不对,最后排查发现是因为第一行输入有一个固定的用例数n,后面跟着n组数据,我读的时候误把第二行的数据当成了第一组数据。

牛客这类ACM模式对输入解析的要求就是老老实实按行读,尤其当数据量大的时候,千万不要用“一次性读所有数据再split”这种方式,容易踩内存或者格式的坑。Python的同学建议用sys.stdin.readline而不是input,C++的同学如果用cin,可以先关掉同步加速,避免超时。

还有多组输入的问题。如果题目没明确说只输入一组,可以用while循环读取到不以EOF结尾,这是最稳妥的方式。但要注意,如果数据里没有EOF标志,这个循环可能永远出不去,所以每一道题都要先确认输入格式再决定读取方式。

输出方面,最常见的坑是结尾空格。很多人习惯在循环里直接 print(ans),但LeetCode模式刷多了,会习惯性地在输出结尾多打一个多余空格,这在ACM模式里可能直接算错。最佳实践是:要么用join拼接,要么在循环里判断当前项是不是最后一个,不是最后一个才打印空格或者逗号。

3.2 数据范围:int不够用怎么办

第二题我其实一开始写的是int,样例过了,但提交之后有几个测试点没过。排查到最后发现,累加全局代价之后的总和超过了int最大值的范围。这个坑在本地测试时很难发现,因为样例数据都比较小。

处理这类问题,最简单的原则是:只要题目涉及累加、求和、乘法,一律考虑用long long。不要相信“这么点数据应该不会超int”这种直觉,笔试数据里经常藏着几组大数用例,就是为了筛掉不看数据范围的人。

Python用户没有这个问题,但C++,Java用户不要偷懒。还有一个隐藏点:如果你用了排序,自定义比较函数里涉及两个数相减,返回值用int没问题,但如果计算过程涉及乘法,中间结果要强转成long long,否则会溢出造成排序结果错误。

3.3 边界条件和特殊用例:为什么样例过了还是零分

这是很多人的真实经历:明明样例和自测用例都过了,提交却0分。我这次在第一题提交前,多测试了两种特殊情况,一种是输入为空的情况,一种是统计目标值本身等于0的情况。这两种情况看着不起眼,但很多模拟题会在这些边界里埋坑。

我也总结过一个检查边界条件的清单:最小输入规模(比如n=1)、最大输入规模(例如n=10^9或10^5)、重复值最多的情况(所有元素相等)、已排序的情况、逆序的情况、目标值等于边界值的情况。笔试时间允许的话,至少把其中三四个跑一遍。

如果提交了0分且完全找不到原因,别继续死磕,先把代码粘贴回来,自己写一个数据生成器来暴力对拍。对拍这个方法,我愿称之为笔试排查第一大杀器。笔试现场写一个能生成随机数据的小脚本,用自己的暴力解和当前提交的解法同时跑,一旦结果不一致,就能定位到是哪种输入类型导致的差异。因为笔试时间有限,不要追求生成全套数据,只生成和题目约束一致的随机数据就够了。

4. 笔试复盘与准备建议

4.1 刷题阶段的优先级参考

经历过这套题之后,我对“笔试到底考什么”有了更现实的认知:它不是竞赛,它考的是“你能否在有限时间内把常见问题写对”。所以刷题阶段的优先级应该是:模板题熟练度 > 边界思维 > 难题攻坚。

这里的模板题包括:二分、前缀和、差分、DFS/BFS、并查集、字典树、拓扑排序、最短路、最小生成树、常见DP模型(背包、LIS、LCS)。这些都是“必须不能丢分”的模块,它的特点是都有一套相对固定的写法,练到肌肉记忆,考场上才能快速写出来。

LeetCode Hot 100和剑指Offer是入门的基础,但要想更贴近笔试风格,一定要练牛客上的历年真题。因为牛客的题更强调输入输出处理,而且数据范围更大,更接近真实笔试。

4.2 代码风格的隐性影响

笔试虽然不要求你写工程级代码,但我越来越觉得,清晰易懂的代码会在你调试时救你一命。我在这次笔试里,把所有逻辑尽量拆成小函数,主流程非常短,后面检查时扫一眼就能判断每一步在做什么。

函数命名也能看出一个人有没有经验:isValid、processTask、computeSum这种命名,看着普通,但在笔试焦虑状态下,效率比a、b、c、d高太多。还有一点,如果你用C++或Java,建议在笔试前提前准备好常用头文件和输入输出模板,考场上复制粘贴能省1到2分钟。

另外,不要为了“短代码”故意压行。笔试中没有代码长度加分,代码写得长一些、清晰一些,换来的调试效率是不亏的。尤其递归的时候,如果每个递归分支都能一眼看出来逻辑,最后检查时你会觉得自己是在读一篇结构清晰的文章,而不是在猜一段天书。

4.3 每一轮笔试后的考试复盘

笔试结束后,不管结果如何,我强烈建议马上把自己能记住的题目记录下来,包括题目描述、数据范围、你的思路、卡住的原因,以及正确解法的推导过程。这次笔试的第三题,我就是靠回忆复盘,把树上路径查询的几种可能的处理方式从头推导了一遍,后面遇到类似问题就不会再慌。

这个复盘记录,不需要很正式,它是一个属于你自己的题目银行。过一段时间回头看看,你会发现自己经常在什么类型的题目上栽跟头。有的人是字符串解析,有的人是DP状态设计,有的人是边界条件遗漏。知道了自己的薄弱点,针对性刷题,效率比盲目刷题高得多。

笔试只是过程的一部分,但不是全部。我见过笔试过线但面试没准备充分的,也见过笔试成绩一般但面试逆风翻盘的。关键是每一轮都从实战里拿经验,下一轮做得更好一点。

5. 最后再分享两个小技巧

第一个是:笔试前可以花15分钟把所有你常用的模板手打一遍,不是为了背诵,而是激活肌肉记忆。你会发现,考场上写二分和并查集的时候,手比脑子还快,这种惯性是真的能节省精力。

第二个是:如果你发现自己第二题卡住了,超过10分钟没有思路,别在那边继续耗着。先跳去做第三题的暴力版,拿完该拿的分数再回头想第二题。这个“先抢分再攻坚”的顺序,在笔试中大概率是收益最高的策略。我自己遇到好几次,跳出去写别的题之后,回来看卡住的题反而有了新思路。

OPPO这套题考下来,整体感受是:不偏不怪,但它会把你平时的训练痕迹暴露得很彻底。如果平时刷题只是“看懂了思路”就划走,笔试一定会被精准打击;如果你平时练习时模拟了完整的输入输出、边界检查、自测用例,那笔试不过是一场带时间限制的日常练习而已。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询