news 2026/9/12 12:01:23

网易内推笔试编程题全解析:四类核心算法考点与代码实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网易内推笔试编程题全解析:四类核心算法考点与代码实战

2017年网易内推笔试的编程题合集,到现在还经常被很多准备校招的人翻出来当练手素材。原因其实很简单:这套题不搞偏题怪题,覆盖的字符串处理、动态规划、贪心、位运算这些方向,恰恰是企业内推笔试里最常见的考察点,而且每道题都有“暴力能拿部分分、优化能拿满分”的层次感,非常适合用来检验自己的真实水平。

这篇文章我会站在一个刷题老手的角度,把这套题里几个高频考点还原成可复现的典型题目,给出完整的解题思路和参考代码,再把最容易踩的坑挨个说清楚。无论你是刚开始准备笔试的在校生,还是想系统梳理算法基础的职场人,都可以直接照着练。至于题目本身,是复盘多份面经后整理出的同类型题,具体表述可能和原题不完全一样,但考点和解题逻辑是相通的,这点很重要。

1. 网易内推笔试的整体设计逻辑:先看懂“题外话”

1.1 内推笔试和统考笔试定位完全不一样

很多人有一个误区,觉得内推笔试和官网统一笔试考的东西差不多,随便准备一下就行。实际上这两个场景的定位差异非常大。网易的内推笔试通常启动更早,一般在七八月就开始,说白了就是提前锁定一部分候选人,所以筛选逻辑会比统考更看重“有没有培养潜力”,而不仅仅是“会不会做题”。

从题目风格上看,内推笔试更偏向算法思维和工程习惯的混合考察。编程题占比很高,而且往往不给你太多可以钻空子的余地。它不像选择题那样能蒙,代码能不能跑通、边界情况处理得干不干净,一眼就能看出来。所以准备内推笔试,重点不是背题,而是把常见题型的思路练成条件反射。

另外,内推笔试有很强的“阶梯淘汰”属性。第一轮机试可能只要求过部分用例,但后续面试官会直接拿你的代码来聊,问“你这里为什么用 HashMap 不用数组”“你的复杂度是多少,能不能优化”。这就意味着,你不仅要写对,还要知道自己为什么这么写。这篇文章后面的分析也会一直贯穿这个思路:先讲清楚为什么这么做,再给代码。

1.2 题型分布与时间分配的底层逻辑

复盘当时笔试的题目构成,可以明显看到一个规律:试卷里不会只堆难题,而是由易到难分成几个梯度,让不同水平的候选人都能被有效筛出来。

  • 第一梯度是热身题,一般是字符串或简单模拟,考察基本编码能力和细心程度。这类题不拿满分会很吃亏,因为区分度恰恰体现在“简单题是不是真的写得又快又对”。
  • 第二梯度是动态规划和贪心,这部分是区分度最高的区域,能筛掉只会背模板、不懂变通的人。
  • 第三梯度是数学思维或位运算,题面短,但需要看破本质,属于拉开差距的题目。

时间分配上,一套卷子三到四道编程题,比赛时间一般控制在90到120分钟。我的建议是拿到题目先花五分钟通读全部题目,不要硬着头皮从第一题开始卡。热身题大约控制在20分钟以内,中档题每道25到35分钟,最后一题如果15分钟内没有思路,果断先把前几题的边界情况补一补,确保已有代码拿稳分数。

2. 四道经典真题的思路拆解:从暴力到最优

2.1 字符串题:最长无重复字符的子串

先看一道热身级别的字符串题,但它考察的点其实不止滑动窗口这么简单。题目描述大概是这样的:

给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。比如输入abcabcbb,最长无重复子串是abc,长度是 3;输入bbbbb,最长子串是b,长度是 1。

我第一次做这个题的时候,第一反应就是暴力:枚举所有子串,再用一个 Set 判断每个子串是否有重复字符。这个思路在字符串长度很短的时候完全可行,但笔试里字符串长度往往给到 10^5 级别,暴力枚举的 O(n^2) 复杂度一定会超时。

正确的姿势是用滑动窗口。你可以把它想象成一个能够伸缩的窗口在字符串上从左往右滑,窗口里永远保证没有重复字符。窗口右边界每往右扩展一格,就看一下新字符是否已经在窗口里出现过;如果出现过,就把左边界挪到上一个相同字符的下一个位置,保证窗口里只保留当前最长的无重复段。

这里有一个特别容易翻车的细节:更新左边界时,不能直接用left = last[c] + 1,而是要用left = max(left, last[c] + 1)。因为 last 数组里记录的是字符上一次出现的位置,但这个位置可能已经不在当前窗口的有效范围里了。比如字符串abba,当右边界走到第二个a时,字符a上一次出现的位置是 0,但此时左边界已经在 2 的位置,如果直接把 left 覆盖成 1,窗口就会错误地包含重复字符,答案就错了。

2.2 动态规划题:网格最小路径和

中档题里动态规划出现的频率相当高,常见的一种考法是把 DP 包装在网格或矩阵场景里。题目类似这样:

给定一个 m 行 n 列的网格,每个格子里有一个非负整数,你从左上角出发,每次只能向右或向下走一步,到达右下角时,经过的路径上所有数字之和最小是多少?

这个题最容易踩的坑是试图用贪心:每一步都选当前格子右边或下边较小的那个数走。但贪心在这里是不成立的,因为局部最优不等于全局最优。举个很简单的反例,一个 2×3 的网格,第一行是 1, 1, 1000,第二行是 2, 1000, 1,从左上角出发,按贪心策略第一步会往右走,但最优路径其实是先向下再向右再向下再向右。

正确的思路是动态规划。设dp[i][j]表示从左上角走到格子(i, j)时的最小路径和。因为只能从上方或左方过来,状态转移方程就是:

dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]

初始化时需要注意:第一行只能从左边一路走过来,所以dp[0][j] = dp[0][j-1] + grid[0][j];第一列只能从上面一路走下来,所以dp[i][0] = dp[i-1][0] + grid[i][0]。这是大多数初学者写错的地方,因为这两个初始化没做对,后面整个递推就全乱了。

空间上还可以优化。观察转移方程可以发现,计算当前行时只需要用到上一行的结果,所以完全可以用一维数组滚动更新,把空间复杂度从 O(m×n) 降到 O(n)。在笔试环境下,这种空间优化不一定能影响你是否通过,但面试官问起来的时候,能答出这一层会加分不少。

2.3 贪心题:最多能参加多少个会议/活动

贪心是面试里绕不开的题型,网易这类公司尤其喜欢考一类:区间调度问题。简化版题目如下:

你有 n 个会议,每个会议有一个开始时间和结束时间,同一时间只能参加一个会议,问最多能参加多少个完整的会议。输入每行两个整数,分别表示开始时间和结束时间,输出一个整数表示最多能参加的会议数量。

如果只是凭直觉,很多人会想到按会议时长排序,优先参加时间最短的。这个思路看起来对,但在区间调度里是错的。更离谱的是按开始时间排序,越早开始的越优先,这个策略同样会翻车。

正确策略是:按结束时间从早到晚排序,优先选结束时间早的会议,然后跳过所有开始时间早于上一次已选会议结束时间的会议。为什么结束时间早就一定更好?因为一个会议结束得越早,给后面留下的时间越多。用数学一点的话说,在所有可行解里,贪心选择的第一个会议一定可以替换成结束时间最早的那个会议而不影响最优解的数量,这一步交换论证是整个贪心正确性的核心,面试时能讲清楚这一点会显得你对算法理解很扎实。

实现上还有一个容易忽略的点:如果两个会议结束时间相同,怎么排序都可以,只要比较器本身是自洽的,不会出现compare(a,b)compare(b,a)同时返回负数这种非法情况。如果直接用a.end - b.end做差值,在两个 end 都是很大的整数时可能出现整数溢出,稳妥做法是使用Integer.compare(a.end, b.end)

2.4 位运算题:数组里只出现一次的数字

这类题属于“一看就会,一做就废”的类型,因为题面非常短,但要求你对底层运算有很深的理解。题目描述是:

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素都恰好出现两次,请找出那个只出现一次的元素。要求时间复杂度 O(n),空间复杂度 O(1)。

看到空间复杂度 O(1),第一反应就应该排除用 HashMap 或 HashSet 的做法。这道题的标准解法是位运算:把数组里所有数字做异或运算,最终结果就是只出现一次的那个数字。原因是异或运算满足交换律和结合律,而且一个数和自己异或等于 0,0 和任何数异或还等于这个数自身。于是所有成双成对的数字会全部抵消掉,剩下的就是唯一落单的那个。

这个题的变种也很值得准备:如果除了一个元素只出现一次以外,其余每个元素都恰好出现三次,又该怎么找?这个就得换个思路了,简单异或不再适用。一个可行的方案是统计每一位上 1 出现的次数,然后对每一位取模 3,最后拼装出答案。这个做法时间 O(32n),空间 O(1),在笔试里也属于常考变体。

3. 完整代码实现与易错点说明

3.1 各题参考代码

说再多不如把代码写出来。下面给出四道题的参考实现,语言我混用 Java 和 Python,笔试时用哪个顺手就用哪个,但核心逻辑必须吃透。

第一题,最长无重复字符的子串,用 Java 写滑动窗口:

public class Main { public static int longestUniqueSubstr(String s) { if (s == null || s.length() == 0) { return 0; } int[] last = new int[128]; java.util.Arrays.fill(last, -1); int left = 0, res = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (last[c] >= left) { left = last[c] + 1; } last[c] = i; res = Math.max(res, i - left + 1); } return res; } public static void main(String[] args) { java.util.Scanner sc = new java.util.Scanner(System.in); String s = sc.nextLine(); System.out.println(longestUniqueSubstr(s)); } }

这里我用了 128 长度的数组来存储字符上次出现的位置,而不是 HashMap。因为题目如果只含 ASCII 字符,数组会比 Map 快很多。如果字符串可能包含中文或其他 Unicode 字符,可以把数组长度改到 65536 或者直接用 HashMap。

第二题,网格最小路径和,用 Java 写一维滚动数组版本:

public class Main { public static void main(String[] args) { java.util.Scanner sc = new java.util.Scanner(System.in); int m = sc.nextInt(); int n = sc.nextInt(); int[] dp = new int[n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int val = sc.nextInt(); if (i == 0 && j == 0) { dp[j] = val; } else if (i == 0) { dp[j] = dp[j - 1] + val; } else if (j == 0) { dp[j] = dp[j] + val; } else { dp[j] = Math.min(dp[j], dp[j - 1]) + val; } } } System.out.println(dp[n - 1]); } }

注意读取方式和 DP 更新是在同一个双重循环里完成的,这样就不需要先把整个 m×n 网格都存在内存里,输入多大的数据都不怕内存爆炸。

第三题,会议安排,用 Java 实现贪心:

public class Main { static class Meeting { int start, end; Meeting(int s, int e) { start = s; end = e; } } public static void main(String[] args) { java.util.Scanner sc = new java.util.Scanner(System.in); int n = sc.nextInt(); Meeting[] meetings = new Meeting[n]; for (int i = 0; i < n; i++) { int s = sc.nextInt(); int e = sc.nextInt(); meetings[i] = new Meeting(s, e); } java.util.Arrays.sort(meetings, (a, b) -> Integer.compare(a.end, b.end)); int count = 0; int lastEnd = 0; for (Meeting mt : meetings) { if (mt.start >= lastEnd) { count++; lastEnd = mt.end; } } System.out.println(count); } }

第四题,找出只出现一次的数字,用 Python 写:

def single_number(nums): res = 0 for x in nums: res ^= x return res if __name__ == "__main__": n = int(input()) arr = list(map(int, input().split())) print(single_number(arr))

这四段代码单独拿出来都不是很长,但每一行都要做到能解释清楚“为什么这么写”,尤其是边界判断和排序比较器这两处。

3.2 代码里那些“看着对了但会挂”的细节

笔试和平时刷 LeetCode 最大的不同是:平台会对代码做很多极端测试,包括超大输入、空输入、单元素输入、重复元素很多等。你就算思路全对,也可能因为几个细节挂掉大半用例。

第一个高频翻车点:字符串题里更新左边界的逻辑。刚才已经强调过,一定要用left = max(left, last[c] + 1),而不是直接赋值。还有一点,last数组初始值必须是 -1,不能是 0,否则当字符在位置 0 第一次出现时,你会误判它已经出现过,直接把左边界向右推,导致结果偏小。

第二个高频翻车点:DP 初始化位置。很多人写网格 DP 的时候只初始化了dp[0][0],然后从(1,1)开始循环,第一行和第一列就直接变成默认值 0,算出来的答案全是错的。我的习惯是先把输入读进来,然后单独处理第一行和第一列,最后再用双重循环计算中间部分,虽然代码长一点,但逻辑更清晰,不容易漏。

第三个高频翻车点:会议题里比较器写法。Java 8 的 lambda 写起来简洁,但如果你用了Comparator.comparingInt(a -> a.end)这种写法,最好把泛型类型写清楚,否则某些老版本编译环境会报类型推断错误。另外,别在比较器里用减法求差值,两个 int 相减可能溢出,面试官看到这种写法也会印象不好。

第四个高频翻车点:位运算题的输入格式。题目一般会给一个整数 n 表示数组长度,下一行给 n 个数字。如果字符串里有多余空格,用 Python 的 split 处理没问题,用 Java 的Scanner也问题不大。但如果你用BufferedReader自己解析,就一定要考虑开头的空白字符,我见过有人因为没 trim 导致多读了一个空字符串,程序直接异常退出。

4. 笔试现场常见问题与排查技巧实录

4.1 超时的锅,到底背在谁身上

很多同学看到“超过时间限制”就慌了,觉得自己算法不对,其实很多时候只是实现层面的问题。比如最长无重复子串这个题,你用 HashMap 不是不行,但每次charAt拿到的 char 要被自动装箱成 Character,再进 Map,性能开销明显高于直接操作 int 数组。笔试的数据量一大,HashMap 的开销会让原本 O(n) 的算法也跑得很勉强。

另一个常见的超时原因是循环里频繁调用substring。Java 的substring在旧版本里会复制底层 char 数组,虽然新版本改成了共享底层数组,但如果你在循环里大量截取字符串,依然会产生大量临时对象,GC 一频繁,超时就不远了。正确做法是只维护左右下标,最后再用下标计算长度,而不是真的截出子串来。

再说输入解析。很多笔试平台的数据量很大,用Scanner读 10 万行整数时性能很差。如果发现自己的代码在输入读取阶段就花了大半时间,建议换用BufferedReader

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] parts = br.readLine().split(" ");

这套组合拳打下来,读耗时能压缩到原来的三分之一左右。笔试现场如果时间剩得不多,优先检查有没有这种“白送的性能提升”。

4.2 边界条件和数据溢出的翻车现场

边界条件是最容易让人崩溃的,本地测试全过,一提交就错一堆。我总结了几类高频边界问题,大家可以对照自查。

第一类是空输入和单元素输入。很多题目的输入规模有下限,但有些题目没说清楚,你就得自己兜住。比如数组只有一个元素时,异或解法能不能正确返回它本身;比如字符串长度为 1 时,滑动窗口能不能返回 1。这两个场景在代码里都应该是自然兼容的,但如果你用了类似if (s.length() < 2) return 0;这种自以为聪明的剪枝,就完蛋了。

第二类是整数溢出。网格路径和如果数字很大,累加结果可能超过 int 范围。笔试题目如果没说数值范围,优先用long接收中间结果,最后输出时再考虑要不要转回 int。会议题的结束时间同理,虽然 int 通常够用,但用long更稳妥。

第三类是负数和零的处理。位运算题里,负数在 Java 和 Python 中的表现差异很大。Java 的int是有符号的,右移>>会做符号扩展;Python 的整数是无限精度的,负数右移的结果和 Java 不一样。如果在读题时看到输入范围里有负数,一定要先在本地把负数的测试用例跑一遍。

4.3 笔试平台的操作细节

平时刷题用惯了自己的 IDE,到笔试平台上容易手忙脚乱。这里有几个实际经验,希望你别等上了考场才想起要确认。

第一,主类名和包名。牛客网这类平台通常要求 Java 的主类名必须叫Main,而且不能带package声明。很多人写完代码直接在本地跑,忘了改类名,上传之后编译都过不了,白白丢送分题。

第二,输出格式。笔试平台一般只比对标准输出,所以不要在输出里加多余提示文字,比如System.out.println("结果是: " + ans)。这种输出一眼看过去很友好,但判题系统会直接判错。

第三,部分得分机制。有些平台是“过多少测试点给多少分”,不是非黑即白。所以即使你只能写出暴力解法,也一定要交上去,别空着。暴力解过了小数据用例,能拿到三成到五成分数,这比满盘皆输强太多了。

5. 面向这套真题的备战经验与后续扩展

5.1 知识点覆盖地图:从题目反推需要补什么

每次笔试完我都会做一个动作:把遇到的题目考点画成一张“能力覆盖表”,看自己哪些地方是薄弱环节。针对这套题,我建议你按照下面这张表来自查。

题型核心考点需要掌握的解法优先级
字符串双指针、滑动窗口、哈希表最长无重复子串、最小覆盖子串
动态规划状态定义、转移方程、空间优化一维 DP、二维网格 DP、背包类
贪心排序策略、正确性证明思路区间调度、带堆的贪心中高
位运算异或性质、按位统计单次出现、三次出现变体
图论/搜索BFS、DFS、拓扑排序最短步数、连通块数量

看到哪个格子是空的,就专门去补哪块。比如你发现滑动窗口不熟,不要只看题解,至少手写三道同类型题,把left指针的移动逻辑练成肌肉记忆。

另外,这套题里虽然没有明确出现树的题目,但动态规划和贪心的思想在树形题里同样适用,所以不要觉得练完这四个类型就能高枕无忧。后续可以自己扩展做做“二叉树的最大路径和”和“会议室 II”这两个变体,一个是树形 DP,一个是贪心加堆,都属于同一个知识体系的延伸。

5.2 刷题之外的三件事,比多刷十道题还有用

很多人的备战方式就是埋头刷题,刷到后来发现常见的题都会,一到新题还是懵。我的经验是,除了刷题,还得做三件事。

第一件事是限时模拟。笔试的频率和比赛很像,如果你平时做题都是不限时的,上了考场很容易因为紧张而在前两道简单题上浪费太多时间。我的做法是在笔试前一周,每天抽 90 分钟完整做一套模拟卷,闹钟一响就停笔,练的是对每道题时间的感知力。

第二件事是复盘复杂度。每做完一道题,不要急着看下一道,先问自己:这部分算法的空间复杂度是多少?如果不做空间优化,能不能过?面试官如果问我“能不能再优化”,我要怎么回答?这套思维练多了,面试和笔试都会明显轻松。

第三件事是准备一个“错题本”。把每次笔试里因为边界条件挂掉的题记下来,不用记完整代码,只需要记一句话,比如“DP 第一行第一列没初始化”“会议排序比较器别用减法”。开考前翻一遍,能避开一大半低级失误。

6. 最后分享一点我的个人体会

这套网易 2017 内推笔试编程题,难度放在今天看依然很扎实,但并没有到劝退的程度。它真正考察的是你有没有把基础算法理解透,以及你在考场高压环境下能不能保持冷静、按步就班地处理边界和优化。过了那么多年,我回头看自己当初的笔试和面试,最大的领悟不是哪道题该怎么做,而是“会做”和“做对”之间还隔着很多练习。字符串的窗口指针、DP 的初始化、贪心的排序依据、位运算的性质,这些知识点都不难,难的是在有限时间里不出错。如果你能把这篇文章里的每道题都亲手写一遍,把每个易错点都实际踩一遍再改对,我相信你会比大多数只刷题不总结的人走得更远。

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

STM32H7 + FreeRTOS + SDMMC 挂载 FatFs 失败:从 FR_DISK_ERR 到根因修复

STM32H7 FreeRTOS FatFs 这套组合&#xff0c;我在项目里用了很多次&#xff0c;但第一次把 SDMMC 挂进 FreeRTOS 的时候&#xff0c;还是被 f_mount 返回的 FR_DISK_ERR 卡了两天。裸机环境下怎么跑都正常&#xff0c;任务调度一开就挂&#xff0c;这种问题最容易让人怀…

作者头像 李华
网站建设 2026/9/5 14:16:41

Python Django框架库存管理系统源码详解:从数据模型到事务并发控制

简介&#xff1a;这是一套基于Python Django框架开发的轻量级库存管理系统源码&#xff0c;面向中小型企业管理者及Python Web开发初学者&#xff0c;解决日常库存录入、查询、统计与可视化管理等核心需求。资源包共2000个文件&#xff0c;总大小29.27MB&#xff0c;涵盖1653个…

作者头像 李华
网站建设 2026/9/5 16:22:33

open-code-review Claude Code插件安装:2个斜杠命令解锁强大评审

open-code-review Claude Code插件安装&#xff1a;2个斜杠命令解锁强大评审 【免费下载链接】open-code-review Fast, efficient, battle-tested at Alibabas scale. Hybrid architecture code review tool: deterministic pipelines LLM Agent, precise line-level comments…

作者头像 李华
网站建设 2026/9/6 1:01:31

NRST引脚深度解析:从原理到实战排查指南

1. 从一块“假死”的板子说起&#xff1a;NRST到底是个什么神仙引脚 做嵌入式这几年&#xff0c;谁还没被复位折磨过几回。我印象最深的一次&#xff0c;是一块STM32F103的核心板&#xff0c;上电之后LED灯闪了两下就彻底没反应了&#xff0c;按复位键也没用&#xff0c;重新烧…

作者头像 李华
网站建设 2026/9/4 17:05:38

600行代码如何训练出GPT-2:nanoGPT 最小化GPT训练库实战指南

600行代码如何训练出GPT-2&#xff1a;nanoGPT 最小化GPT训练库实战指南 【免费下载链接】nanoGPT The simplest, fastest repository for training/finetuning medium-sized GPTs. 项目地址: https://gitcode.com/GitHub_Trending/na/nanoGPT 如果你想自己训练一个 GPT…

作者头像 李华