☰
网易校招笔试算法题库解析:题型套路与刷题指南
2026/11/3 14:59:28 网站建设 项目流程

2019年秋招那会儿,网易的笔试在互联网大厂里属于很有辨识度的一档:题量不大,但题型覆盖特别规整,难度梯度拉得很长,从刚开始的数组遍历送分题,到后面能卡住一大半人的动态规划和贪心优化,一套卷子刷下来,基本能把一个人的编程底子摸得清清楚楚。标题虽然写着“合集(二)”,但你真做完几套就会发现,合集的价值从来不是背题,而是帮你熟悉网易出题的那套固定套路:题目描述喜欢绕弯,边界条件喜欢埋坑,时间限制压得比牛客其他模拟题更狠。这篇文章把我自己刷题时整理的题型结构、解题思路、踩坑记录完整写出来,适合正在准备校园招聘、尤其是瞄准大厂技术岗的同学参考。

1. 网易校招笔试的整体面貌与选题思路

1.1 笔试环节到底在筛什么人

很多人把笔试理解成“算法竞赛的迷你版”,但网易这类公司的校招笔试和ACM还是有明显区别的。比赛题追求的是“在极短时间内完成极多技巧叠加”,而校招笔试更看重“拿到一个业务场景能不能迅速抽象成程序结构”。同一道题放在LeetCode上可能是一道Medium,放到笔试里就喜欢给你披上业务外衣。

比如网易非常喜欢在题目描述里塞一堆产品文案:“小易的果园里种了n棵苹果树,每棵树供应周期不同”“玩家背包里有若干物品,需要按规则合成”。剥掉这些壳,内核其实就是排序加前缀和,或者哈希表计数。所以第一关要练的不是算法难度,而是读题能力。我建议拿到题目先花三分钟拆解:确定输入规模、找出约束条件、判断时间复杂度上限,再动手编码。

笔试的另一个隐性筛选点是代码规范。网易的在线判题系统对Java和C++都有严格的类名和主函数要求,提交前不看编译错误,一旦编译失败整题零分。我见过太多同学栽在这里:类名写错、忘记导入包、输出多了空格。这些细节在平时刷LeetCode不疼不痒,在校招笔试里就是致命的。

1.2 题型分布与难度曲线

如果把网易2019年秋招的编程题摊开看,分布其实相当稳定。字符串处理、模拟题大约占三成,动态规划占两成,贪心加数据结构占两成,剩下的是搜索、数学推导和思维题。这和阿里、百度相比,少了复杂的图论和高级数据结构,但多了一些对逻辑严密性的考察。

难度曲线通常呈现“两个平台一个台阶”的结构。前两题属于热身题,基本只要会写循环和哈希表就能拿分,主要作用是稳住心态。中间的题开始考察常见算法模板,比如最长上升子序列、区间合并、背包变体,属于区分度最大的部分。最后一题往往是思维题,代码很短,但需要绕过一个关键结论,很多人在这个地方卡到交卷。

我的建议是,练习时不要只刷题不总结,要有意识地把题目归类。一道题做完后问自己三个问题:它属于哪类题型?核心突破口是什么?如果换一个数据范围,解法是否还成立?这样刷二十道,比盲目刷一百道更有效。

2. 高频题型拆解:字符串处理与模拟题

2.1 字符串处理类题目的常见套路

字符串题在网易笔试里出现频率极高,几乎每场都有一道。这类题看起来简单,但往往在细节上做文章。最典型的是“压缩与还原”模型:给定一个由字母和数字组成的字符串,数字表示前一个字符连续出现的次数,要求在解压时处理括号嵌套和多位数字,这背后其实考的是栈结构的使用。还有一种常见变体是把两个带分隔符的字符串按规则合并,核心是双指针加条件判断。

我个人的经验是,字符串题一定要先确认字符集范围。只包含小写字母和只包含ASCII可见字符,对应的数组初始化方式完全不同。用哈希表当然可以,但如果字符范围明确,用固定数组性能会更好。笔试环境里,Java的HashMap在频繁put时会有装箱开销,用int[26]往往能省下不少时间。

另外,字符串题最容易错的是索引边界。比如使用substring截取子串时,endIndex是开区间,少写一个或者多写一个都可能直接数组越界。我习惯在写完代码后,手动走一遍最短输入和最长输入两个边界样例,尤其是空串和单字符的情况。

2.2 模拟题的读题与状态设计

模拟题是网易笔试的重头戏,它们不考高深算法,考的是你能不能把题目描述翻译成准确的状态迁移。典型例子是“游戏角色按规则移动”“系统按时间轴处理任务队列”。这种题的核心不在代码量,而在状态设计。状态多了容易乱,状态少了容易漏。

我的做法是先画状态转移表,把每个时刻需要维护的变量列出来,推演两三个简单例子,确认所有分支都覆盖到再写代码。模拟题最容易翻车的地方是“一轮操作中状态被提前修改”。比如同时更新多个变量时,新值覆盖旧值就会影响后续判断。这时候要么用临时变量暂存,要么严格依照原值计算后一次性赋值。

还有一个实用技巧:模拟题如果时间步数很大,一定要检查有没有循环节。有些题目表面上是模拟一万步,实际上状态会在几十步后进入循环,识别出循环节可以直接把复杂度从O(n)降到O(cycle)。这是网易模拟题里比较隐蔽的加分点。

3. 算法核心:动态规划与贪心策略

3.1 动态规划的常见命题角度

网易笔试里的动态规划题,难度不会太夸张,但非常套路化。最常出现的是“给定一个数组,求满足某种约束的最大值/方案数”,比如不相邻元素和的最大值、股票买卖的最佳时机、编辑距离的变体。解决这些题的关键是定义好状态含义,并且明确状态转移方程的来源。

我举一个高频例子:打家劫舍变体,数组循环首尾相连。很多同学直接套标准线性DP模板,结果在环的处理上出错。正确的做法是拆成两个子问题:不考虑最后一个房间和不考虑第一个房间,分别跑一次线性DP再取最大值。这种“把环拆成两条链”的思路,在网易笔试里反复出现过。

DP题另一个容易丢分的地方是初始化。int数组默认值是0,但如果求最小值,初始值必须设成Integer.MAX_VALUE。同理,如果状态转移里需要比较大小,初始化为0可能是错误的,因为某些路径根本不存在。我的习惯是画一个二维表,在第一行和第一列手动填入不可达状态,再开始递推。

3.2 贪心策略的证明与实现

贪心算法在代码实现上往往比DP短得多,难的是想明白贪心策略为什么成立。网易喜欢考的贪心场景有区间调度、任务安排、分组配对。以任务安排为例:每个任务有截止时间和收益,同一时间只能做一个,求最大收益,这就不能用简单排序解决,得借助优先队列动态维护。

笔试里很多同学看到贪心题就直接选一个自己觉得合理的排序方式,结果样例过了、提交全错。问题往往出在排序依据上。比如“按截止时间排序再按收益决策”和“按收益排序再按截止时间决策”,最终结果完全不同。我的建议是,在写完贪心代码后,必须用一个小规模样例做验算,最好尝试构造一个反例验证策略是否稳健。

另外,贪心题常与堆结合。比如每次从集合里取最大/最小元素,合并之后又放回去,这样需要用一个优先队列维护动态最值。Java里PriorityQueue默认是小顶堆,如果需要大顶堆,要么传Comparator.reverseOrder(),要么插入负值。这个细节写错,整个贪心流程就会完全走样。

4. 数据结构实战:哈希表、堆与单调栈

4.1 哈希表在笔试题中的高频用法

如果只能选一种数据结构应对笔试,我会毫不犹豫选哈希表。网易的题目里到处是它的影子:统计单词频次、判断元素是否存在、标记访问状态、记录元素最后一次出现的下标。哈希表的本质是空间换时间,笔试中几乎不会管你用了多少额外空间,所以该用就用。

有一个经验值得分享:在循环里使用哈希表时,尽量提前计算hashCode,避免重复计算。Java的HashMap在Key是String时,每次查找都要重新算哈希,如果循环次数超过10万,性能差距就会显现。一个简单的优化是,把频繁用到的key先缓存成变量,而不是在循环里反复new一个相同的字符串对象。

另外一个套路是用哈希表记录“前缀状态”。比如求数组中和为k的最长子数组长度,经典的O(n)解法就是利用哈希表存前缀和的首次出现位置。网易经常在这个模型上做文章,变换一下条件,比如乘积等于k、某个条件刚好出现两次等。掌握“前缀和+哈希表”的组合,很多看似复杂的题都能在一分钟内定下解法方向。

4.2 堆与优先队列的实战

堆在网易笔试中通常不会单独出题,而是作为其他算法的辅助结构出现。最典型的场景是TopK问题和大数据流中位数。一个技巧是“大小顶堆对顶结构”:维护一个小顶堆存较大的一半,一个大顶堆存较小的一半,两个堆大小差不超过1,这样堆顶就是中位数。这种思路在笔试现场非常好写,而且不容易出错。

优先队列还有一个妙用是“合并K个有序链表”,网易有时会把它包装成“多路归并日志”之类的场景。实现上,用PriorityQueue存每个链表的当前节点,每次取出最小值,再把它所在链表的下一个节点放入堆中,复杂度是O(nlogk)。很多同学会忘记堆里放的是节点本身还是下标,建议统一放一个封装对象。

另一个常见错误是堆元素的比较器写反。Java的PriorityQueue默认升序,如果自定义类需要按某个字段排序,务必在compare方法里写清楚。我经常看到有人把return a-b写成return b-a,结果取出的顺序完全相反,整个算法直接失效。建议写完比较器后立刻用一个三元组做测试,确保堆顶是你想要的那个元素。

4.3 单调栈的典型场景

单调栈是网易笔试里区分度较高的一种数据结构。它的核心应用场景是“找每个元素左边/右边第一个比它大/小的元素”,典型题目是“柱状图中最大的矩形”“每日温度”。单调栈的代码模板很固定,难的是理解为什么元素出栈时能确定它的边界。

我拿“每日温度”举例:维护一个从栈底到栈顶递减的栈,遍历温度数组,当当前温度大于栈顶温度时,说明栈顶元素遇到了右边第一个更暖的天气,这时记录天数差并弹出栈顶。这个过程每个元素至多入栈一次、出栈一次,时间复杂度O(n)。很多同学会纠结“为什么弹出的元素不会再被用到”,关键在于每个元素只在遇到右侧第一个更大值时弹栈一次,它的结果已经确定了。

单调栈题目的难点在于对“单调”的定义。不同题目可能是严格递增、非严格递减等,写条件时容易出错。我的经验是先从简单样例里手推一遍,确认比较符号,再套模板。只要比较符号写对,单调栈的代码几乎不用改。

5. 实战演练:三道代表性题目的完整解法

5.1 题目:字符串解压还原

题目场景是这样描述的:给定一个压缩字符串,格式是“字母+数字”,数字可以有多位,例如“a3b2c10”,要求输出解压后的完整字符串“aaabbcccccccccc”。数据范围是压缩后的长度不超过10万,解压后的字符串很长但不需要全部存下来,只输出长度即可。这类题的关键在于搞清楚数字解析的边界。

先看一个常见错误:直接从左往右扫描,遇到数字就循环累加字符,但多位数字会被拆成多个字符处理。正确实现应该是:看到数字时,持续往右读,直到下一个字符不是数字为止,组成完整的计数。然后把这个数字乘以当前字符,加入结果。

public long getDecompressLength(String s) { long total = 0; int i = 0; int n = s.length(); while (i < n) { // 当前位置一定是字母 char c = s.charAt(i); i++; int count = 0; // 解析连续的数字,可能有多位 while (i < n && Character.isDigit(s.charAt(i))) { count = count * 10 + (s.charAt(i) - '0'); i++; } total += count; } return total; }

这道题如果只要长度,直接累加即可,但如果要求输出完整字符串,需要小心内存溢出。真正的笔试环境一般不会让你输出那么长的字符串,而是把结果限制在一个可接受范围内。尽管如此,使用long而不是int来累加长度仍是好习惯,因为一旦题目加码,int很容易溢出。

5.2 题目:环形房屋偷窃问题

这类题的场景是:n个房屋围成一圈,每个房屋有一定金额,不能偷相邻房屋,求能偷到的最大金额。由于首尾相连,不能同时偷第一个和最后一个。这个限制比线性版本难,解法是拆成两个子问题:去掉最后一个房屋做一次线性DP,再去掉第一个房屋做一次线性DP,取较大值。

线性DP的状态转移方程很清晰:dp[i]表示偷到第i个房屋时的最大金额,要么不偷当前房屋,保持dp[i-1],要么偷当前房屋,加上dp[i-2]和当前金额。写成代码后,要注意数组长度为1和2时的边界。

public int robCircle(int[] nums) { int n = nums.length; if (n == 1) return nums[0]; if (n == 2) return Math.max(nums[0], nums[1]); // 拆成两个线性问题:不偷首、不偷尾 return Math.max(robLinear(nums, 0, n - 2), robLinear(nums, 1, n - 1)); } private int robLinear(int[] nums, int start, int end) { int prev2 = 0, prev1 = 0; for (int i = start; i <= end; i++) { int cur = Math.max(prev1, prev2 + nums[i]); prev2 = prev1; prev1 = cur; } return prev1; }

这里用滚动变量替代dp数组,空间复杂度降到O(1),也是笔试中值得展示的优化点。边界条件是这类题最坑的地方:数组长度为1时,环的意义不存在,直接返回唯一元素;长度为2时,两者不相邻,取最大值即可。千万不要漏掉这些判断。

5.3 题目:任务调度最少时间

这道题的场景是:给定一个任务列表,每个任务用大写字母表示,同类任务之间有冷却时间n,同一任务连续执行必须间隔n个单位时间,不同任务不受影响,求完成所有任务所需的最短时间。这是经典的贪心加数学推导问题,不是模拟。

关键结论是:出现频率最高的任务决定了最短时间下界。假设最高频任务是A,出现了maxCount次,那么至少需要(maxCount - 1) * (n + 1) + 1个时间单位。但如果有多个任务频率相同,需要把这些并列的“尾部”也考虑进去。最终答案是max(总任务数,计算出的下界)。

public int leastInterval(char[] tasks, int n) { int[] counts = new int[26]; for (char task : tasks) { counts[task - 'A']++; } int maxCount = 0; for (int count : counts) { maxCount = Math.max(maxCount, count); } int maxNum = 0; for (int count : counts) { if (count == maxCount) { maxNum++; } } int minLen = (maxCount - 1) * (n + 1) + maxNum; return Math.max(minLen, tasks.length); }

这道题的推理过程比实现更重要。我建议大家记住这个结论,但更要理解推导原理:高频任务的间隔数量是maxCount-1,每个间隔里至少有n个空闲或其他任务,最后再补上同频率的任务尾部。笔试里如果时间充裕,也可以先用优先队列模拟一遍验证答案,虽然复杂一些,但不容易遗漏反例。

6. 常见问题与排查技巧实录

6.1 时间复杂度过高的典型原因与优化思路

笔试交卷后最懊恼的事,不是没做出来,而是“我的代码明明写对了,但一直超时”。网易的题时间限制普遍是1秒或2秒,Java的常数偏大,如果你用一个O(n^2)的算法处理10万级别的数据,基本没有生还可能。

我的排查顺序是:第一,看数据范围。如果n大于10万,尽量别用两层循环。第二,看空间换时间的可能性,比如用哈希表替代线性查找。第三,看能否排序后利用单调性。举个例子,求两数之和的变体,暴力法是O(n^2),排序加双指针能降到O(nlogn),用哈希表能降到O(n)。笔试中优先选第三种。

还要注意Java的IO问题。如果你用Scanner读取大量数据,性能远不如BufferedReader。网易有些题目的输入规模很大,Scanner可能直接导致超时。我习惯在笔试模板里直接写好BufferedReader的封装,节省现场重新编写的成本。

6.2 边界条件与数组越界的那些坑

边界条件是我自己刷题时踩过最多的坑,尤其是数组下标边界。很多题目在正常区间内测试都正确,一旦遇到空数组、单元素数组、数值溢出、字符串空串,就立刻崩溃。比如二分查找的结束条件写错,会在数组长度为2时死循环;滚动DP的索引写错,会在数组长度为2时越界。

一个我特别推荐的兜底策略是:写完每个算法后,先构造最小规模的输入手动跑一遍。最短数组是什么,最长数组是什么,极端值是什么。这些用例必须在提交前跑通。网易的判题系统在遇到Runtime Error时,不会告诉你越界的位置,只会直接报错,所以自查非常重要。

另有一个隐蔽问题是整数溢出。比如求中位数时写成(left+right)/2,left和right都很大时会溢出,应该写成left+(right-left)/2。类似地,累加金额、计数时优先用long,避免乘积和求和在int范围内溢出,这类错误在LeetCode上不常见,但在网易笔试的压力环境下经常被忽略。

6.3 输入输出处理与代码模板准备

校招笔试的最后一关是输入输出。网易使用牛客网平台,输入输出格式和LeetCode完全不同,很多平时只刷LeetCode的同学第一次面对“自己写main函数、自己解析输入”时会不知所措。最常见的输入格式是:第一行一个整数T表示测试用例组数,然后每组数据有两行或三行。

我建议提前准备好一个固定的输入模板,把Scanner或BufferedReader的初始化、多组用例的处理、字符串分割和整数解析封装好,每次套用即可。例如,读取一行数据后直接用split(" ")分割成数组,再逐个转成整数。

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; while ((line = br.readLine()) != null && !line.isEmpty()) { String[] parts = line.split(" "); int a = Integer.parseInt(parts[0]); int b = Integer.parseInt(parts[1]); System.out.println(a + b); }

还有一个容易被忽略的点:题目要求输出字符串严格匹配,不能有多余空格和换行。网易的多组数据输出通常要求每组占一行,如果你在循环里多打印了一个空行,判题系统直接判Wrong Answer。这种错误最冤,务必在提交前检查输出格式。

最后分享一个我自己的习惯:平时刷题时,我会给每道题标记三个标签——题型、数据范围、最优复杂度。遇到新题时先在脑海中检索对应的标签,快速锁定解法方向。网易的笔试风格稳中有变,但只要把字符串、模拟、动态规划、贪心、基础数据结构这五个大模块练透,再加上一个稳定的输入输出模板,通过笔试并不难。毕竟笔试只是衡量你在有限时间内解决业务问题的能力,不是要求你成为算法竞赛选手。

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

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

立即咨询