尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

牛客网2018一模编程题刷题攻略:从题型解析到笔试实战

牛客网2018一模编程题刷题攻略:从题型解析到笔试实战 1. 这套模考题是什么适合谁来刷1.1 2018年牛客一模的背景与价值如果你在校招季前逛过牛客网对“模考”这个词应该不陌生。牛客的模考一模系列可以理解为正式笔试前的全真模拟——题目风格、难度分布、输入输出格式都尽量贴近当年各大厂笔试的真实氛围。2018年这套编程题集合A现在回看依然有很强的参考价值因为它的题型分布非常经典字符串处理、数组操作、简单模拟、基础数学计算占了绝大部分几乎没有偏题怪题属于“稳扎稳打型”的试卷。我当时刷这套题的第一感受是它不考你多高深的算法不搞线段树、不搞网络流、不搞后缀自动机考的全是“基本功”。但恰恰是这种基本功在真正笔试的时候最容易翻车。为什么因为几十个同学同时交卷编译不过的直接零分超时的直接淘汰边界情况没处理的扣掉大半用例。这套模考卷的意义就是帮你提前暴露这些问题让你在真正的笔试之前把低级失误清干净。所以这套题适合谁我总结下来有三类人。第一类是正在准备校招的应届生尤其是目标岗位是后端、前端、测试开发这类要考编程题的同学第二类是刚学完数据结构、想检验自己编码基本功的在校生第三类是工作几年后想跳槽需要重新捡起刷题手感的人。如果你是这三类中的一员这套卷子花两个周末过一遍性价比非常高。1.2 别等简历被刷才想起来刷题很多同学有个误区觉得刷题是临近笔试才做的事简历投出去等通知的时候才开始慌。实际上牛客模考这类东西最好的刷法是在投简历之前就做一遍。因为你做完一套你大概就知道自己现在是什么水平——是能在45分钟内AC两道题还是憋了一个小时连输出格式都没搞对。这个自我评估比任何模拟面试都诚实。另外这套卷子虽然标着2018年但它的题目质量并不过时。编程题的考察内核一直很稳定读题能力、边界处理能力、基础数据结构的应用能力。现在笔试虽然偶尔会冒出一些新玩法比如交互式题目、系统设计题但大部分公司的技术笔试仍然以这类传统编程题为主。把2018年的卷子吃透再去做近两年的真题你会发现很多思路是通用的。我当时就是先刷了这套一模再去做当年的秋招真题明显感觉心理上有底了。2. 题型分布与考察重点拆解2.1 高频题型字符串、数组、模拟是老三样2018牛客一模A的题型分布和当年大部分公司笔试的出题思路高度一致。我大概统计了一下整套卷子的编程题可以分为三类字符串类约占三分之一。常见考法有字符串翻转、子串统计、字符去重、简单模式匹配。难点不在算法而在边界判断——比如空串、全空格、大小写混合、末尾换行符处理。数组与数学计算类约占三分之一。常见考法有求最大最小值、数组去重、累加累乘、质数判断、进制转换。这些题本质上是考你对循环和分支的掌控力。模拟类约占三分之一。给你一段业务规则让你按要求一步步操作。这类题不考算法技巧考的是“把自然语言翻译成代码”的能力。翻译得准不准决定了你能过多少测试用例。这个分布比例在很多公司的笔试卷里都能看到甚至可以说是一套“保守但有效”的筛选逻辑字符串考细心数组考逻辑模拟考理解能力。三者都不需要太高深的算法知识但对代码基本功的要求很实在。如果你能把这三类题稳定地在30分钟内做出两道以上你已经超过了相当一部分笔试候选人。2.2 难度梯度设计低中高题怎么拉开区分度这套卷子的题目排序也有讲究整体难度是逐步爬升的。前面的题基本上是“送分题”只要思路对代码量很少10到15行就能搞定。中段的题开始加码有了输入范围限制比如数据量到10的5次方要求你用O(n log n)的算法这时候暴力解法就会超时。最后面的题往往是“纸老虎”——题目描述很长场景很复杂但拆解之后核心逻辑并不复杂考验的是你在有限时间内快速理解规则并落地代码的能力。我当时做完后复盘发现一个有趣的规律拉开分数差距的往往不是最后那道难题而是中间的“中等题”。因为简单题大家都会难题大家都做不出来中等题的正确率才是区分度最大的区域。这套卷子里的中等题恰好是那种“你觉得自己会但一提交就有一两个用例过不去”的类型。所以刷这套题的时候不要把精力全耗在最后一道题上中段题才是拿分的关键区域。我建议刷题时这样分配时间前20分钟扫一遍所有题目按难度打个标记先稳拿两道简单题再攻中等题最后剩的时间再看难题有没有可拿的部分分。这个策略听起来老套但在真实笔试里非常管用。3. 典型题目思路还原3.1 字符串类基础题别小看翻转和去重我记得这套卷子里有一道字符串翻转题不是简单的逆序输出而是要求翻转单词顺序比如输入 “I am a student.”输出 “student. a am I”。这道题属于典型的“一看就会一写就错”。直白的思路是先对整个字符串做一次整体翻转再对每个单词做局部翻转。整体翻转后变成 “.tneduts a ma I”然后按空格切分对每个单词再翻转一次就能得到目标结果。这里有一个关键点切分字符串的时候不同语言的处理方式不一样。用C的话要自己处理空格间隔用Python的话直接split()很省事但要注意多个空格连续出现的情况。用Java的话String是不可变的操作起来会生成大量中间对象刷题阶段不推荐但也不是不能做。我当时用Python实现的时候踩过一个坑用split( )和split()的结果不一样。前者会保留空字符串元素后者会自动忽略连续空格。这个细节在本地跑代码的时候不容易发现但牛客的判题系统用例覆盖得比较全一旦用例里有连续空格split( )就会输出错误结果。这类题目考的不是“会不会翻转”而是“有没有处理特殊输入的意识”。我后来总结出一个习惯凡是涉及字符串拆分的题默认先想清楚分隔符有多复杂——多个空格、制表符、首尾空格这些都要手动画出来测试一下。3.2 数组与数学计算边界条件是分水岭数组类题目里让我印象很深的一道是“求数组中的第k大元素”。这道题在LeetCode上是中等题但牛客模考里它的输入描述做了些变化第一行输入n和k第二行输入n个整数要求输出第k大的数。n的范围给到了10的5次方意味着你不能用那种每次删除最大值的蠢办法。常见的解法有几种第一种用堆维护一个大小为k的小根堆遍历一遍数组堆顶就是第k大的数。时间复杂度O(n log k)空间O(k)。第二种快速选择Quick Select平均复杂度O(n)最坏O(n²)但通常跑得快。第三种直接排序后按下标取值复杂度O(n log n)虽然理论上可行但如果你的排序写得不稳也容易超时。我在刷这道题时的体会是边界条件比算法本身更容易让你丢分。比如k1的时候小根堆的大小是1直接比较就行kn的时候其实求的是最小值你的代码要能处理这种极端输入。还有一个细节输入是否允许重复数字如果允许重复那么“第k大”的定义是什么是去重后的第k大还是不去重的第k大这道题的描述里没有特别说明但我试了两种理解发现牛客的用例是按不去重处理的。这个要靠读题经验——如果题目没有明确说“去重”默认就是不去重。另外还有一个数学类的经典题给定一个正整数n判断它是否是质数。这道题看着简单但考查的是你对时间复杂度敏感度的判断。如果你老老实实从2遍历到n遇到10的12次方级别的输入铁定超时。正确做法是遍历到 sqrt(n)并且可以先排除偶数和2进一步减少一半计算量。我当时把判断质数封装成了一个函数这套模考题后面有两三道题都复用了这个函数节省了不少时间。3.3 模拟题把题目翻译成代码的能力模拟题是这套卷子里最需要耐心的一类。我记得有一道题描述了一个复杂的业务场景——具体来说是关于排队叫号的过程有A、B、C三种客户类型每种类型的办理时长不同客户按到达时间排队但有VIP客户可以插队要求输出每个窗口处理的客户列表。这道题一看描述就吓人实际上核心逻辑就是维护一个优先级队列以及若干个普通队列。我当时拿到这种题习惯性的处理方式是三步走。第一步先把题目里的规则用自己的话复述一遍写到草稿纸上确认自己理解了规则而不是似懂非懂。第二步找出题目里的“实体”和“动作”实体是客户、窗口、队列动作是到达、排队、办理、离开。第三步为每个实体设计数据结构。这一步想清楚了代码就是顺着流程往下写。这道题真正难的不是数据结构而是“VIP插队”这个规则的处理。如果先到先得队列和VIP队列分别维护什么时候把VIP队列的人插入到普通队列前面是在新客户到达的时候还是窗口空闲的时候题目描述可能只说“VIP优先”但不告诉你具体是哪种触发时机。这种情况下我建议先按“窗口空闲时优先从VIP队列取人”来实现如果用例没过再调整。因为窗口空闲时检查VIP队列逻辑最简单也最容易排查问题。这道题做完我对模拟题的心态发生了一些变化——不再怕长题目了反而觉得长题目信息量大反而容易从描述里找到提示。4. 笔试现场的时间分配与实战策略4.1 先读题后动笔优先级排序方法在牛客这种OJ系统上做笔试时间管理的重要性甚至超过技术能力。我见过太多同学拿到卷子就闷头做第一题做完一道就花掉了40分钟结果后面明明有更简单的题却没时间写。真实的校招笔试两个小时三道题是常态。这套模考卷也差不多所以一定要养成先读题的习惯。我的做法是前10分钟不做任何代码把所有题目都看一遍。一边看一边给每道题打三档标记——“稳拿”的题是那种描述很短、事件逻辑清晰、你立刻能想出完整解法的题“需要想一想”的题是有思路但边界情况需要仔细处理的题“没头绪”的题是那种看完两眼发直的题通常也是分值最高或描述最长的题。然后按“稳拿优先”的顺序作答先保证有两道AC在握再回头啃需要想的题。用这套模考题来说字符串翻转、判断质数这类题属于“稳拿”档应该优先写。排队叫号那类模拟题属于“需要想一想”档放在第二顺位。如果最后还剩时间再去看“没头绪”的题哪怕只能过部分测试用例也能拿一些分。牛客的判题通常按测试用例数量给分部分通过好过交白卷。4.2 语言选择与调试习惯关于笔试用什么语言我的观点比较明确用你最熟悉、最不费脑的语言。很多同学纠结“Java还是C还是Python”其实在牛客笔试里三种语言都可以提交没有绝对的优劣。关键在于考场上你需要的是肌肉记忆——比如用Python写遍历、用C写STL容器脑子里不需要额外思考就能敲出来。我自己笔试主用C因为刷题时用得多但遇到字符串处理比较多的题我偶尔会切Python因为处理起来更省事。切换语言的前提是两种都用得熟如果你只是半吊子那还不如一门语言用到底。调试方面我的经验是不要依赖在线调试器实际上很多笔试环境根本不给调试器。你要学会给自己写“肉眼可见的调试输出”——在关键分支打印中间变量确认数据流转是否符合预期。但这里有个细节提交前必须把所有调试输出注释掉或删除。我见过不止一个同学代码逻辑完全正确就因为多打印了一行中间结果导致输出格式和预期不符被判零分。这是一个非常可惜的低级失误建议你在刷模考题的时候就养成习惯写完代码后先检查一遍有没有多余的打印语句再点击提交。还有一个习惯是“提交不着急”。牛客模考的判题反馈很快但不要用“提交-看结果-再改”的方式来排除错误。正确做法是先在本地想清楚所有测试用例包括边界条件自己构造几个极端输入跑一遍确认无误后再提交。这样一次AC率会高很多也更能模拟真实笔试时的心态。5. 刷题过程中最常见的坑5.1 边界条件和数据范围我统计了一下我刷这套模考卷时将近70%的WAWrong Answer都出在边界条件上。这不是我一个人的问题几乎每个刷牛客的同学都会遇到。最典型的几个边界条件包括输入为空、输入为一个元素、输入为最大值、输入全是相同值、输入已经有序或完全逆序。这些情况在样例测试里很少出现但判题系统的用例会覆盖。拿“判断质数”这道题来说n2和n3是质数n1和n0不是质数n是负数也要考虑。有些同学直接忽略负数情况虽然题目可能限定为正整数但万一描述里写得模棱两可你就有风险。我在刷题时养成了一个强制习惯每道题写完核心逻辑后强制列举三个边界输入来测试。第一个是“最小合法的输入”比如数组长度为1第二个是“最大范围的输入”比如n10的9次方或字符串长度为10000第三个是“带有重复或极端字符的输入”比如字符串里全是空格或全是同一个字符。这三组用例跑通了再提交AC的概率会大幅提升。5.2 输出格式和空行问题输出格式是另一个容易阴沟翻船的地方。牛客的判题对空格、换行、大小写要求很严格有时候多一个空格都判错。尤其是“输出所有符合条件的元素空格分隔”这类描述很多同学会在最后一个元素后面也打个空格这在部分OJ里没问题但在牛客的某些题里会被判错。更隐蔽的是空行问题。有些题要求每组输出之间用一个空行隔开最后一组之后没有空行有些题要求每行输出后都没有多余空格。如果你在本地IDE里看不出来可以把输出重定向到文件用十六进制查看末尾有没有奇怪的字符。当然刷模拟题的时候不需要这么较真但你要有意识地保持代码整洁——用循环变量判断当前是不是最后一个输出项是的话就不打分隔符。我记得有一次我刷这套卷子里的数组题本地样例输出完全正确但提交后有一个用例失败。排查了半天发现是题目要求“如果结果为空输出空行”我没有处理这个分支。这种用例虽然不是核心逻辑但一旦出了就是用例不过。从那以后我在读题时会特别留意“空结果”这种情况的处理要求。5.3 超时与复杂度优化牛客笔试的超时限制一般是1到2秒如果你的算法复杂度太高即使答案正确也会被TLETime Limit Exceeded。这套模考卷里数据范围比较大的题目集中在数组类上比如前面提到的第k大。很多同学在初学阶段习惯用暴力解法——双重循环嵌套一时写起来很爽但数据量一大就原形毕露。我建议在动手写代码前先大概估算一下时间复杂度如果你看到n是10的5次方你的双重循环就是10的10次方次操作在1秒内基本不可能完成这时候哪怕要用写的代码多一点也得换思路。正所谓“暴力一时爽提交火葬场”这个教训是我刷牛客刷出来的。还有一个常被忽略的点输入输出效率。用Python写笔试的时候如果数据量大print和input的频繁调用也会影响性能。这种情况下建议把所有输出先放到一个list里最后统一用\n.join()输出输入则用sys.stdin.read()一次性读进来再按行处理。C选手则可以考虑用ios::sync_with_stdio(false)和cin.tie(0)来加速输入输出。这些细节在数据量小的时候看不出来但数据量一上来可能就是1秒和1.5秒的区别。6. 从模考到校招我的个人经验6.1 复盘比刷题更重要做完这套模考题最重要的一步不是看自己AC了几道而是系统地复盘。我的做法是建立一个简单的表格列出每道题的题型、耗时、是否AC、WA原因、TLE原因、最优复杂度。然后横向对比找出自己的规律——比如我发现自己的WA原因集中在边界条件因为我在写循环时经常忘记处理首尾元素另一类问题是“读题过快理解偏了”比如把“第k大”理解成了“第k小”。这些问题在复盘之后变得非常清晰下次再遇到同类场景时我会本能地多看一眼题目描述里的关键词。关于要不要看题解我的原则是一道题如果想了30分钟还没有任何可行的优化方向再看题解。但不能只看一份题解至少要比较两种不同解法比如堆和快排都可以解决第k大问题两种都写一遍感受它们在不同数据下的表现。只抄一遍题解是最低效的学习方式因为那不是你的思路你只是把别人的答案从屏幕上搬到了你的代码里。6.2 从A卷到B卷后续还可以怎么扩展2018年牛客模考一模不仅有A卷还有B卷和其他场次。我的建议是A卷做扎实之后把B卷也刷了。两套卷子对比着看你会发现出题人的偏好——哪些知识点反复出现哪些坑是故意设计的。这种对比性训练比单刷一套卷子更有效。另外这套卷子的主题还可以扩展方向把普通数组题替换成链表、二叉树版本把字符串翻转替换成自定义分隔符的切分把排队叫号模拟题换成更复杂的状态机场景。牛客网每年都有新的笔试题和真题集你可以顺着这套模考的题型去刷对应知识点在近两年的真题变化。比如2018年的char数组题现在可能考的是字符串匹配或回文串以前考模拟排队现在可能考LRU缓存设计。技术点的内核没有变但场景和数据结构复杂度在升级。我个人最大的感受是牛客模考的价值不是“押题”而是让你提前进入笔试状态。很多东西你明明知道但在时间压力下就容易犯蠢。比如忘记初始化变量、在循环里改变了迭代器的值、字符串比较用了而不是equalsJava选手的血泪史。这些低级错误平时慢慢写根本不会犯但考场上就是会发生。刷模考就是让你在低成本环境下把这些错误全部暴露一遍然后带着这些“免疫记忆”走进真正的笔试考场。最后说一个我在刷完这套卷子后调整的心态不要把AC率看得太重把“能从每次提交失败中学到什么”看得更重一点。这套题让我进步最大的是我终于养成了“先写测试用例再写核心逻辑”的习惯以及“写完代码后立刻用极端数据压测”的条件反射。这些东西后来我写工程代码时也一直在用受益匪浅。
返回列表