
1. 这场考试的真实面貌题型分布与时间压力先说一个很多人不愿意面对的事实网易这批内推笔试编程题一般在三道左右时间却往往只有一个半小时到两个小时。看起来时间充裕实际上大部分人是做不完的。我当年拿到试卷的时候第一反应是怎么就三道题稳了结果十几分钟后我发现第二道动态规划的题目连状态定义都没想清楚第三道题更是一眼看过去就头皮发麻。这不是在吓唬你而是想让你在真正坐到考场前就建立正确的预期这场考试的核心不是让你全部做完而是让你判断出哪些该做、哪些该放。2017年的这批内推笔试题整体风格偏重基础算法和思维能力题目难度呈现明显的梯度变化。第一题通常比较友好要么是字符串处理要么是简单的数学规律题目的是让大部分人能拿到基础分。第二题开始上强度常见的是动态规划或者需要一点思维技巧的模拟题这里会筛掉一部分刷题量不够的人。第三题往往是拉分题可能是比较复杂的DP状态压缩、二分答案结合贪心也可能是需要踩不少坑的数据结构操作能完整AC的人就已经是少数了。从知识点覆盖面来看这类考试几乎不会考特别偏门的算法像什么后缀自动机、网络流这种你基本可以不用准备。它考的还是那几样字符串、数组、栈和队列、链表、树的基础遍历、二分查找、贪心、动态规划的基础到中等题型。换句话说考察的是你的基本功是否扎实以及你在有限时间内能不能把思路转化成代码。顺便说一句当年很多人挂在了一个看似无所谓的地方输入输出。笔试平台用的是牛客网之类的在线评测系统输入格式有时候藏着坑比如多组数据没有明确告诉你结束条件或者是用空格还是换行分隔不写清楚。你代码逻辑写得再漂亮读入数据的地方写错了直接就是0分。这个问题我在后面会专门展开说因为它真的比你想的更容易翻车。1.1 编程题的数量与难度梯度如果你去翻往年的面试经验帖会发现2017年前后的网易笔试编程题出题风格其实有一条隐藏的规律第一题通常考察字符串或简单数学第二题是动态规划或贪心第三题属于综合应用题往往需要把两到三种基础技巧组合在一起才能解出来。比如第一题可能是这样给一个字符串让你按某种规则重新排列字符输出字典序最小的结果。这类题不难但它会考察你对字符串API的熟悉程度以及边界条件的处理能力。有人用C的std::sort一把梭有人用Python的排序函数都能过但如果你对语言自带的排序稳定性、自定义比较函数的写法不熟就得在调试上消耗不少时间。第二题和第三题就不一样了。我记得当年网上讨论比较多的是一道关于任务排期的动态规划题输入是每个任务的耗时和截止时间要求找一个最优顺序使得总延迟最小。这题第一眼看上去很像贪心——按截止时间排序不就行了吗但仔细一推发现如果任务的处理时间不一样简单的排序就会出错必须用DP来枚举状态。这种看着像贪心实际要DP的题目恰恰是网易这类公司最爱出的。因为它在短时间内就能区分出哪些人只是刷过题型哪些人是真正理解了算法背后的逻辑。1.2 时间分配决定了你会不会做不完我的建议非常直接拿到试卷后先花一分钟快速浏览所有题目不要从第一题开始死磕。为什么要这样做因为大部分人的心态是从头到尾按顺序做结果第一题如果卡住了心里就开始慌后面的题目都带着焦虑去做原本能想出来的也想不到。正确做法是先扫一眼题面把题目分成能秒想一想能做基本可以放弃三档。然后先把能秒的题做掉拿到稳妥的分数再回头啃中间的题最后一档直接不碰节省时间用于检查和补充。在时间分配上我个人的经验是第一题最多给二十分钟第二题三十分钟第三题如果能做就做超过四十分钟还没有完整思路就果断放弃。笔试的评分不是按题目难度的加权分来算的而是你通过了多少用例就得多少分部分通过的用例同样算分。所以第三题哪怕只能跑到部分用例也比空在那里强。1.3 别被笔试平台机制坑了网易这批笔试用的平台和很多公司一样代码提交后会有个编译运行的反馈。但有个很多人忽略的点平台不会告诉你每个测试用例的具体输入是什么只会告诉你通过了百分之多少的用例。这就意味着你无法通过构造特定输入来猜测出题人的数据范围。我的习惯是无论题目有没有说数据范围我都假设最坏情况。比如题目说n在1000以内我会先写一个O(n^3)的暴力试一试如果TLE了再优化。笔试环境里时间有限先拿到正确但复杂度的结果比一上来就闷头写最优解最后时间不够要强太多了。2. 字符串与模拟类题基础分题目里的隐藏陷阱说实话网易的第一道编程题大多数情况下是字符串处理或者模拟题难度不高但细节极多。很多人在LeetCode上刷过不少Medium题目信心满满结果到了笔试里却被第一题卡了半小时这种例子我见得太多了。为什么会这样因为刷题网站上你面对的是明确输入的单个函数但笔试里你要处理的是完整的输入输出程序包括从标准输入读数据、按格式输出、处理多组测试数据等等。如果这些基础能力不熟做题节奏就会被打乱。2.1 字符串处理的经典考法2017年这批笔试里字符串题目可以说是常客。通常会给你一个字符串让你按照某种规则变换之后输出结果。表面上是考字符串操作技巧实际上是在考察你对循环边界字符编码大小写转换字典序比较这些基础知识的掌握程度。举个我当时见过的类似题目给定一个字符串要求把所有连续的重复字符合并成一个并且按合并后的顺序输出。听起来特别简单对吧但当你真的写起来会发现几个容易出错的点。循环遍历的时候从第0位开始和从第1位开始边界判断不一样容易导致最后一个字符漏处理。连续判断不能只比对前一个字符因为aaabbb这种多个字符交替的情况如果逻辑写不对会把不相邻的重合字符也算进去。输出的时候注意不要额外多输出空格或换行在OJ平台上这种错误叫Presentation Error虽然不算错但会浪费你一次提交机会。我给的参考解法是这样C#include iostream #include string using namespace std; int main() { string s; while (cin s) { // 注意多组输入的情况 string result; for (char c : s) { if (result.empty() || result.back() ! c) { result.push_back(c); } } cout result endl; } return 0; }这段代码的核心逻辑就是当前字符和前一个保留的字符不相同才加入。但如果你用的是当前字符和原字符串中前一个字符不同就加入就会漏掉中间被合并的字符输出结果会一直错。这就是我说的隐藏陷阱——思路差一点点结果就差很多。2.2 模拟题不是照着写就行模拟题是另一个高频考点。所谓模拟题就是题目描述了一个规则或流程让你用代码把这个过程走一遍。它不考察高深的算法但考察你把文字描述转换成代码结构的能力。网易2017内推笔试里头出现过一类模拟题和多线程任务调度或者排队叫号有点类似有若干个人排成一列每个人有一个处理时间系统按某种规则依次处理问某个时间点在处理谁或者队伍最后的结束时间是多少。这类题看着绕但核心就是找到正确的数据结构去模拟。队列是最常见的因为先进先出的顺序天然符合排队语义。但有些题不是先进先出而是按优先级处理这时候就要用优先队列堆。我之前见过一个考生他写模拟题的时候在循环里用了vector的erase操作每次删除一个元素导致整个vector整体搬移本来O(n)的操作变成了O(n^2)数据一大就超时。其实换成queue就完全没问题。模拟题的优化思路往往不在算法层面而是数据结构选择的层面。2.3 这类题怎么写才能拿全分模拟和字符串这类基础题拿满分的秘诀其实就两个字细心。我总结了一套固定的答题清单每次写完之后按这个清单自查是否考虑到了空字符串、空数组、单个元素这些极简输入字符比较的时候是区分大小写还是不区分题目有没有明说大小写不敏感输出格式是每行一个结果还是每个结果用空格分隔行尾有没有多余空格数据范围有没有超过int的极限需不需要用long long如果题目有多组输入循环结束条件是什么是读到EOF还是读到一个特定值不要觉得这些问题低级。实际笔试里大部分人挂掉恰恰就是因为这些低级问题。我在第5点吃过一次大亏有一道题数据给到了10^9我用int存结果溢出变成了负数输出全错还找不到原因白白浪费了20多分钟。从那以后凡是看到数量级、较大的数这类字眼我都直接用long long保险起见甚至用long long的前提下再做一次范围判断。3. 动态规划与贪心拉分题的核心套路网易这批笔试第二题和第三题才是真正拉开差距的地方。它们通常考察的就是动态规划和贪心偶尔会考二分答案或图论的最短路但频率远没有前两者高。我见过太多人一看到DP两个字就直接心态爆炸。其实大可不必。动态规划在笔试里真的没有你想象的那么高不可攀只要你掌握了一套套路大多数中低难度的DP题都能解出来。3.1 一眼看出DP状态的练习方法很多人学DP第一个困惑就是我不知道怎么定义状态。其实这里有一句口诀题目问什么状态就存什么。比如题目问前n个物品能组成的最大价值那状态f[i]就是前i个物品能组成的最大价值。如果题目问到达第i个位置的最小步数那状态f[i]就是到达第i个位置的最小步数。这个看似废话的口诀真的能解决80%的题目。剩下的20%怎么办往往是题目不是直接问一个数字而是问是否可行或者有多少种方案。这时候状态就要加上题目给的限制条件。比如有多少种方案可以凑出金额target状态f[i][j]就是前i个硬币凑出金额j的方案数。如果你能练习到看完题面十秒钟之内就能写出状态定义DP题对你来说就不再是拦路虎。怎么练就是刻意练习。每做一道DP题不要急着写代码先在同一张纸上写下三个东西状态定义、状态转移方程、初始状态。这三个东西写清楚了代码就是翻译工作。3.2 贪心题怎么证明自己是正确的贪心其实比DP更容易翻车。因为贪心的思路往往很短——你想到一个局部最优能得到全局最优的结论但很难证明它是对的。很多人在笔试中凭直觉写了一个贪心结果挂在部分用例上非常可惜。我自己的判断标准是如果一道题你能构造出一个反例推翻这个贪心策略那它就不是贪心题如果你找不到反例而且题目明显有每一步选最优的特征那大概率就是贪心。但更稳妥的方法是先用暴力/搜索验证小数据量下的正确性。笔试时间再紧你总可以写一个暴力算法去跑几个n很小的情况和贪心的结果对比一下。如果一致你可以放心提交如果不一致赶紧换思路。这里给出一个2017年网易笔试很典型的贪心 二分组合题河里有n块石头青蛙从第一块跳到第n块允许最多跳k次问你青蛙每次跳跃的最短长度最大是多少。这种题如果你按贪心直接模拟每次尽量往后跳那可太容易出错了。正确的套路是反向思考答案一定是一个长度检查如果限制每次跳不超过X能否用不超过k次跳到终点这个检查过程用贪心每次尽量跳最远然后二分X找最大可行值。复杂度从暴力的O(n^k)降到O(n log M)完全是两个世界。3.3 典型DP题拆解与代码我在准备这批笔试时刷到过一道很值得展开讲的题题面大概是这样的有一排货物每个货物有重量和价值你有一个容量固定的箱子要在不超过容量的前提下装下最大价值。这其实就是经典的0-1背包但网易的变体是货物可以拆成一半放进去也就是说如果你放不下整个货物还能放一半价值和重量都减半。这题的DP状态比较好想到f[i][j]表示前i个货物容量为j时的最大价值转移的时候对每个货物考虑三种情况不选、选整个、选一半。n, W map(int, input().split()) w [] v [] for _ in range(n): wi, vi map(int, input().split()) w.append(wi) v.append(vi) dp [[0] * (W 1) for _ in range(n 1)] for i in range(1, n 1): for j in range(W 1): # 不选 dp[i][j] dp[i-1][j] # 选整个 if j w[i-1]: dp[i][j] max(dp[i][j], dp[i-1][j-w[i-1]] v[i-1]) # 选一半 if j w[i-1] // 2: dp[i][j] max(dp[i][j], dp[i-1][j-w[i-1]//2] v[i-1]//2) print(dp[n][W])注意这里面有几个容易踩的坑。第一重量和价值折半时题目到底是用整数除法还是允许小数如果允许小数你需要把重量放大两倍变成一个整数问题。第二容量可能是巨大的二维数组会内存溢出这时候就要用滚动数组优化——把dp[i][...]压缩成dp[...]因为每一行的状态只依赖上一行。第三输入的多个货物可能有重复重量不能简单用set去重。我当年做题时就把一半理解错了以为是对原始值四舍五入拿到了一堆WA。后来才发现题目说的一半是向下取整而且箱子容量必须是整数。这种坑光靠想象力是避不开的只有多练习、多踩坑才会长记性。4. 解题顺序与调试策略在有限时间内拿最多的分这一节可能是全文最有用的部分因为不管你会不会写某道题合理的答题策略都能帮你多拿几分。笔试的分数直接影响你是否进入下一轮面试而面试官在看你的笔试成绩时往往更关注通过率而不是是否全部AC。4.1 拿到题后前5分钟要做什么我的习惯是前5分钟不敲代码只做三件事。第一读题。不是扫一遍而是逐字读完尤其是输入输出格式那一段里面有大量的坑。第二手算样例。按照题目给的输入自己用笔算一下看能不能得到题目给的输出结果。这一步非常重要因为它能帮你验证你对题目的理解是否正确。如果手算出来的结果和题目给的不一致那说明你的理解有问题早点发现可以避免后面白写代码。第三标注数据范围。把题目中的n、m、容量、人数这些数字圈出来判断复杂度要求估算需要使用什么级别的算法。这三件事做完你对这道题就有了一个清晰的全局画面。接下来再动手敲代码你会发现思路顺畅很多。相反如果你拿到题就开始写代码写着写着发现漏了条件回头改的时候往往越改越乱。4.2 卡住时的切换策略笔试时遇到不会做的题太正常了。关键在于你怎么处理你大脑的死机状态。我的经验是如果一道题思考了20分钟还没有任何进展果断跳过做下一题。这不叫放弃这叫战略性止损。你要意识到笔试时间是你的稀缺资源把时间花在一个大概率做不出来的题上不如花在能拿部分分的其他题上。但跳过不等于完全不管。你可以在草稿纸上留下你的思路哪怕最后没时间写完整代码你也要把暴力解的框架写上去。因为很多笔试平台是部分通过给部分分暴力解通常能通过30%到50%的用例这比你空着强太多了。如果你在检查时发现一道题部分用例没过优先检查这几个地方数组越界、整型溢出、循环结束条件、变量初始化。我统计过大部分部分通过的问题都出在这几类。4.3 本地调试和隐藏用例笔试平台的测试用例是隐藏的你看不到具体数据只能看到通过率。这时候本地调试就成了你的救命稻草。建议你在本地IDE里先生成一些简单用例甚至手工构造一些刁钻用例来测试。比如空输入、单元素输入、超大输入、全是重复值的输入。把你能想到的边界情况都测一遍往往能揪出很多隐藏问题。另外给你一个特别好用的小技巧如果你怀疑某个整数运算可能溢出你可以在本地把两个极端的数代入看看输出的结果大致量级对不对。如果发现结果变成了负数或者极不合理的大数那基本就是溢出。5. 笔试题型背后的能力考察从面试官视角看内推筛选逻辑很多人把笔试当成做题比赛以为刷够LeetCode就能稳过。其实站在面试官的角度笔试设置的考察点远不止算法本身它还有筛选信息的深层逻辑。5.1 算法基础 vs 工程能力网易这类公司筛选候选人最主要看三件事算法思维、代码规范、工程素养。算法思维不用多说就是你能不能把复杂问题抽象成数学模型用合适的数据结构和算法去解决它。这是笔试首先要看的。代码规范则是很多程序员面试的时候才注意到的东西但笔试其实已经在考察。你提交的代码里变量命名是否清晰有没有写关键注释代码结构是否整洁这些细节在面试官看到你的笔试代码时会被自然注意到。虽然自动评测系统只关心结果对不对但如果你有后续的面试环节面试官可能会翻看你当时的笔试代码这时候你的代码风格就会影响他对你的第一印象。工程素养考察的则是你能否写出在真实场景下可运行的代码。比如你处理输入输出的方式是否健壮有没有考虑大数据量时的时间空间开销这些同样是工程素养的一部分。5.2 从岗位匹配看笔试设计网易的内推笔试不同岗位的题目其实会有侧重点。技术与研发岗算法题是主流测试开发岗可能多一道和测试思路相关的题数据岗概率统计和SQL相关的题目会占一定比重。虽然2017年这批笔试题目以纯算法为主但你在准备时最好还是按照自己投递的岗位去准备不同的侧重点。投了客户端开发就要多练练字符串、数组、界面状态管理模拟这类题投了后端就要多看看和系统设计、高并发、IO处理相关的代码题投算法岗DP和图论就得烂熟于心。不要拿着一套题海战术套所有岗位那是典型的低效准备。5.3 将一次笔试经验转化为长期能力我个人觉得笔试之后最重要的不是纠结分数而是复盘。准备好一个备忘录记录下每道题的题型、你的解题思路、卡住的地方、以及最终的解法。一周之后回头再看你会对自己的能力图谱有更清晰的认知。也会有很多人问内推笔试还能不能搜到原题说实话像网易这种大厂笔试题目的保密性做得比较好但历年题型和风格在网上还是有迹可循的。你可以在牛客网、CSDN、知乎上搜到很多往届考生的回忆帖和经验总结这些对你了解题目风格和难度非常有帮助。我在准备的时候会把网上能找到的历年真题分类整理分成字符串、模拟、DP、贪心、搜索等几个大类然后针对每一类集中练习。这样比盲目刷200道LeetCode效率高得多。因为笔试题目虽然每年都在变但解题的核心套路基本是固定的。掌握了套路你面对的是一个又一个老朋友而不是陌生人。再补一句我在实际操作中摸索出来的小经验在做编程题练习时尽量模拟真实的笔试环境——在OJ平台上、用完整的输入输出结构来写而不是在IDE里只写个函数。这两个东西的体验差距非常明显你早早适应了笔试节奏真正上场时就不会因为怎么读多个用例这种问题浪费宝贵的时间。