校招笔试这道坎,过来人分享点实在的。京东2017校招技术岗客观题(二),放在今天看依然是一套很有参考价值的卷子。我想写这篇并不是因为题本身记得多牢,而是那套卷子考完后,我和不少一起进面的同学对过答案,再加上后来自己整理错题,发现它把应届生最该打牢的计算机基础查了个遍。准备校招的同学,或者工作两三年想回过头补基础的朋友,都可以把这篇当作一份考点复盘和避坑手册来看。
先说个整体结论:这套客观题不偏不怪,难度中等偏上,但覆盖面广、题量不小,很多题目的坑不在考得多深,而在考得细。数据结构、算法、计算机网络、操作系统、数据库、编程语言是绝对主力,还夹杂了少量概率统计和场景分析题。下面我从整卷结构到具体考点,再到做题顺序和易错点,一条龙拆开讲。
1. 试卷整体布局与命题逻辑
1.1 题型结构与知识模块分布
那年技术岗客观题(二)的题型是常规的单选题加多选题组合,部分批次还出现了几道判断题。题目数量我记得在50到60道之间,答题时间90分钟,平均下来一道题只有一分半左右。这个节奏其实挺紧的,因为很多题不是一眼能看出答案的,需要动笔演算。
从知识模块的分布来看,大致是这么个比例:
| 模块 | 大致占比 | 典型考察方式 |
|---|---|---|
| 数据结构与算法 | 30%-35% | 复杂度计算、二叉树遍历、排序稳定性、栈与队列特性 |
| 计算机网络 | 15%-20% | TCP握手、HTTP状态码、TCP/UDP区别、IP地址计算 |
| 操作系统 | 15%左右 | 进程线程、死锁条件、页面置换、内存管理 |
| 数据库 | 10%-15% | SQL语法、索引原理、事务特性、范式判断 |
| 编程语言 | 10%左右 | C++构造析构顺序、Java集合与异常、指针与引用 |
| 概率统计与其他 | 5%-10% | 概率计算、逻辑推理、智力题 |
这个分布说出来大家可能觉得平淡,但它恰恰代表了校招笔试的主流思路:先筛掉基础不牢的,再筛掉临场心态差的,最后留下来的才有资格进面试。所以别指望笔试考多前沿的技术,考的就是教科书上那些最核心的概念,只不过换了一层迷惑性很强的外衣。
1.2 客观题为什么爱考“基础广度”而不是“项目深度”
我刚准备校招的时候也很不理解,我项目里明明用过Spring Cloud、写过分布式锁,为什么笔试不考这些,偏要考什么死锁的四个条件、B+树的非叶子节点存什么。后来想明白了:校招候选人那么多,笔试作为第一道筛选,必须用统一标准、快速量化地评判大量候选人。项目这东西千人千面,没办法标准化打分,而基础题可以。
更关键的是,技术基础反映了一个人的学习潜力。你今天会把框架用好,不代表你三个月后能快速上手新框架;但如果你能把操作系统和网络的底层逻辑讲清楚,说明你具备举一反三的底子。京东那套卷子在这个逻辑上执行得很彻底,几乎没有超纲题,所有考点都在考研大纲和主流教材覆盖范围内。所以准备这套题,本质上就是在准备一个“计算机基础知识点全扫描”。
2. 核心考点与典型题解析
2.1 数据结构:栈、队列与二叉树是绝对主力
数据结构这块,栈和队列几乎每年必考,考察方式也很多样。最常见的一类就是出栈序列合法性判断。比如给一个入栈序列a、b、c、d、e,问下列哪个不可能是出栈序列。这种题看着简单,但选项里故意放一个迷惑项,很容易选错。
做题的核心就一句话:模拟栈的行为,随时检查栈顶。以入栈序列abcde为例,如果第一个出栈的是c,说明a和b已经入栈且还在栈里。栈是先进后出,所以后面出栈的顺序必须是b在a之前。如果出栈序列里出现了某个元素在它之前入栈的元素还没出栈,那这个序列就非法。我记得那套卷子里的具体选项记得不太清了,但这种题只要有耐心在草稿纸上画个栈模拟一遍,基本不会出错。
二叉树也是重头戏,考察点集中在遍历序列还原、完全二叉树节点编号、以及二叉树的性质计算。有一类高频题:已知前序遍历和中序遍历,求后序遍历,或者问这棵树有几个叶子节点。这种题必须熟练掌握“前序定根、中序划左右”的还原思路。前序遍历第一个节点是根节点,然后拿着这个根在中序遍历里找到位置,左边是左子树、右边是右子树,递归处理即可。考场上时间紧,建议直接用笔在括号表示法里写,不要画完整的树图,画图太耗时。
哈希表的冲突处理方式(开放定址法、链地址法)也是客观题常客,经常和查找成功/失败的平均查找长度搭配考察。计算平均查找长度的题,牢记逻辑是“按哈希函数算出位置,再从这个位置按冲突处理规则往后找,找到空位或找到目标为止,记录比较次数”。
2.2 算法:复杂度、排序与动态规划
算法题里,时间复杂度计算是送分题也是最容易丢分的题。二分查找O(log n)、快排平均O(n log n)、最坏O(n^2)、归并排序O(n log n)且稳定,这些要像背乘法口诀一样熟练。那套卷子里应该出现了辨析排序算法稳定性的题:稳定的排序有冒泡、插入、归并、基数;不稳定的有选择、快排、堆排、希尔。很多同学分不清选择排序和插入排序谁稳定,记住一句话:选择排序每次找最小值和当前位置交换,交换可能把相同元素的相对顺序打乱,所以不稳定;插入排序是把新元素插到有序序列的合适位置,不改变已有元素的相对顺序,所以稳定。
动态规划和贪心的区别也是高频考点。经典教材题:背包问题里,为什么0-1背包不能用贪心而分数背包可以。原因很简单:0-1背包选了某个物品就不能再选另一个,可能存在“当前局部最优导致全局最差”的情况,而分数背包可以把物品掰开装,局部最优能累积成全局最优。这类题考的不是你能不能写出状态转移方程,而是你对两种算法适用边界的理解。
还有一类智力型的算法题,比如找假币、倒水问题、两个人轮流取石子谁必胜。这类题看着吓人,其实都是固定套路。取石子这类博弈题,核心是判断“必胜态”和“必败态”,如果当前状态能一步转移到必败态,那当前就是必胜态;如果所有转移都到必胜态,那当前就是必败态。从小状态往上推就能找到规律。
2.3 计算机网络:三次握手、HTTP状态码与TCP/UDP
网络部分,三次握手是雷打不动的考点。不仅要记住SYN、SYN+ACK、ACK这个流程,还要理解为什么是三次而不是两次。因为两次握手无法让双方确认彼此的接收和发送能力都正常。具体说,客户端发送SYN后,服务器能确认自己收得到、发得出;但服务器回SYN+ACK后,客户端如果没有再回一次ACK,服务器无法确认客户端是否收到了自己的SYN,因为可能存在旧的SYN请求让服务器误以为连接建立。
关于TCP和UDP的对比,客观题喜欢考察“哪个协议基于TCP”或者“哪个应用用UDP”。HTTP、FTP、SMTP、Telnet都是TCP;DNS、DHCP、SNMP、视频直播走UDP。考得细一点会问每个字段占多少位,比如TCP头部源端口和目的端口各16位、序号和确认序号各32位。
HTTP状态码的考察也不能忽视。2xx表示成功,3xx表示重定向,4xx是客户端错误,5xx是服务器错误。301和302的区别是易错点:301是永久重移,302是临时重移。搜索引擎优化场景里,301会传递权重,302不会,这个即使不做SEO也能记住,程序员写接口时常会用到。403表示服务器拒绝请求,404表示资源不存在,500是服务器内部错误,502是网关错误,503是服务不可用。这些数字背后的业务含义,最好都留个印象。
子网划分和IP地址计算也是传统题目。2023年了,IPv6都普及不少,但笔试题里还是爱考IPv4。给定IP和子网掩码,算网络地址、广播地址、可用主机数,方法就是“掩码与IP逐位与运算得到网络地址,然后把网络地址的主机位全置1得到广播地址”。记住这两步,网段计算题的半边天就稳了。
2.4 操作系统:进程线程、死锁与内存管理
操作系统这模块,最经典的就是进程和线程的区别。“进程是资源分配的基本单位,线程是CPU调度的基本单位”这句话几乎是标准答案,但题目会把它换着花样考。比如哪个变量是线程之间共享的,哪个是各自独立的。全局变量、静态变量、堆上的数据是线程共享的;栈上的局部变量和线程的寄存器状态是独享的。如果做多选题,一定要把“栈空间各自独立”这个选项选上,这是高频正确选项。
死锁的四个必要条件(互斥、持有并等待、不可剥夺、循环等待)也是必考,而且经常反向考:破坏哪个条件可以避免死锁。比如资源一次性分配是破坏“持有并等待”,可剥夺资源是破坏“不可剥夺”,资源有序分配法破坏“循环等待”。我见过不少同学把“循环等待”和“持有并等待”搞混,这里留意一下,前者强调形成环路,后者强调占着不放还继续申请。
内存管理里,页面置换算法值得重点准备。OPT最佳置换、FIFO先进先出、LRU最近最久未使用、Clock时钟置换。客观题经常给一串访问序列和固定页框数,让你算缺页次数。FIFO会出现Belady异常(分配页框增多但缺页次数反而增加),LRU不会。这个点200%值得记住,是选择题里很爱设的陷阱。
虚拟内存和分页分段的分工也要分清楚。分页是系统视角,解决内存碎片和程序大于物理内存的问题;分段是用户视角,按逻辑模块划分,方便共享和保护。一道经典判断题:分页对程序员完全透明,分段是可见的。前半句对,后半句也对,但如果题目说“分段对程序员完全透明”,就是反的。
2.5 数据库:索引、SQL与事务特性
数据库客观题主要集中在索引原理、SQL语法、事务特性和范式判断。
索引这块,B+树几乎是标准答案。B+树为什么适合做数据库索引?两个点:非叶子节点只存关键字不存数据,一个节点能存的索引项更多,树更矮,IO次数更少;叶子节点用链表串起来,做范围查询非常高效。相比哈希索引,B+树支持范围查询和排序,哈希索引只能做等值匹配,这点对比题高频出现。
SQL题里,常用聚合函数加GROUP BY的组合,尤其是找分组后满足条件的组,要用HAVING而不是WHERE。还有一个经久不衰的经典题:查找第二高的薪水。我给出一种通用写法:
SELECT MAX(Salary) FROM Employee WHERE Salary < (SELECT MAX(Salary) FROM Employee);如果题目要求“如果没有第二高返回NULL”,则外面再套一层:
SELECT IFNULL( (SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1), NULL );这类题关键是要理解子查询和聚合函数的嵌套顺序,不要一上来就想着排序、LIMIT、OFFSET,那样容易漏掉并列的情况。
事务ACID特性是送分题,但也容易被细节坑到。原子性、一致性、隔离性、持久性四个特性分别对应什么问题,要能对上。隔离级别有四个:读未提交、读已提交、可重复读、串行化。每个级别能解决什么问题,比如脏读在“读未提交”下会存在,在“读已提交”后消失;不可重复读在“可重复读”级别消失;幻读一般要靠串行化或者间隙锁解决。MySQL默认的可重复读,实际上通过Next-Key Lock解决了大部分幻读问题,但这属于进阶知识,客观题问到“默认隔离级别”时,填可重复读即可。
范式判断也是校招老熟人。判断第几范式,先找主键,再看有没有部分依赖(非主属性依赖主键的一部分)和传递依赖(非主属性依赖其他非主属性)。第一范式要求字段原子性,第二范式消除部分依赖,第三范式消除传递依赖。考题经常给一个二维表,问它属于第几范式。第一步看有没有重复组,第二步看主键是不是联合主键,如果是联合主键是否存在非主属性只依赖其中一部分,结合这两点基本能定位。
3. 实战解题流程与时间分配
3.1 拿到试卷后先做的事
很多人拿到卷子就开始从头到尾顺着做,我建议不要这样。客观题试卷信息量大,从头做到尾很容易在前面卡住,导致后面简单题没时间做。我的习惯是先把试卷扫一遍,快速标记出三类题:一眼能出答案的、需要动笔算的、完全没思路的。
一眼能出答案的题先做掉,比如“下列哪个排序算法是稳定的”这种,记住直接选。需要动笔算的题放在第二梯队,比如二叉树还原、平均查找长度、子网划分、缺页次数,这类题必须争分夺秒但不要恋战,如果两分钟内没有清晰思路,先标记跳过。完全没思路的题直接留到最后,能蒙就蒙。
这套策略的依据很简单:客观题每一道分值相同,不存在“难题值更多分”的情况,把时间花在能拿分的地方才是理性选择。我当年就是把一道页面置换的题算了四分钟,结果后面三道基础题差点没时间做,差点翻车。
3.2 读题和排除技巧
很多人丢分不是因为不会,而是因为没看清题目。技术客观题最爱玩“以下哪项是错误的”,注意是“错误的”不是“正确的”。我建议在读题时把“不正确”“不属于”“不能”“除非”这些否定词圈出来,做题时下意识提醒自己是找反例。
排除法在单选题里效率极高。四个选项,如果有一个铁定错,有一个明显太绝对(带“一定”“必须”“全部”的选项往往是错的),剩下的两个里通过对比细节基本能锁定。比如排序稳定性那道题,出题人经常把“快速排序稳定”塞进选项,这个就是无论如何都要划掉的干扰项。
多选题的策略更特殊。多选的规则一般是不选、错选不得分,少选可能得部分分。这意味着你不需要追求选满,只需要保证每个选定项都是高置信度。如果一道多选你有三个选项非常确定,第四个模棱两可,建议就选三个,拿部分分远好过贪心全错归零。
3.3 计算题的草稿规范
客观题涉及计算的不少,但草稿纸就一张,如果写得太乱,回头检查时根本找不到刚才算到哪一步。我建议计算题按题号分区块写,每道题留出一个小方块,最后答案单独写在方块角落。比如页面置换题,就把访问序列写在最上面、页框状态的变化一行行往下列,缺页用圈标出来。这样不仅检查方便,而且手写过程本身就能帮你理清思路,减少因为看错下标导致的低级错误。
说到时间分配,我给自己定的红线是:前面60%的题花40%的时间,中间30%的题花40%的时间,最后10%的题花20%的时间。这类卷子往往前段数据结构计算量大,中段网络操作系统相对快,后段概率统计和智力题见仁见智。把时间结构切成这样,能保证最耗时的部分有充足预算,而不是闷头做前面导致后面连连跳车。
4. 高频易错点与避坑清单
4.1 那些“差一个字就反转”的坑
我把这套卷子踩过的坑和后来收集到的错题集中整理了一下,有几个高频误区值得单独说一说。
第一个是快速排序最坏时间复杂度。很多人一看到快排就选O(n log n),完全忽略“最坏”两个字。快排最坏发生在每次划分都极度不均匀时,比如在近似有序的序列上选固定基准,时间复杂度退化到O(n^2)。题目如果问“平均”或“一般”,答O(n log n)没错;问“最坏”,必须按O(n^2)处理。
第二个是TCP的第四次挥手。三次握手大家都熟,但连接释放是四次挥手。考试爱问的是TIME_WAIT状态出现在哪一端、持续多久。答案是主动关闭方、持续2MSL。很多人记成被动方,或者记成出现在三次握手里,这个大坑每年葬送不少人。
第三个是进程与线程的资源共享。题目说“不同线程之间不共享的是哪个”,很多人选堆,这是错的。堆是共享的,线程私有的是栈和寄存器上下文。只要把“线程共享:全局区、堆、文件描述符;线程私有:栈、寄存器状态、线程ID”这条编成口诀,这题就稳了。
第四个是SQL中的NULL。任何与NULL做算术比较的结果都是UNKNOWN,不等于空字符串,也不是0。比如WHERE Salary = NULL查不出任何结果,必须用IS NULL。这道题在笔试里出现率极高,而且错得相当隐蔽。
我把这些坑整理成一张速查表,方便考前最后翻一遍:
| 知识点 | 常见错误 | 正确答案 |
|---|---|---|
| 快排最坏复杂度 | O(n log n) | O(n^2) |
| TIME_WAIT所在端 | 被动关闭方 | 主动关闭方,持续2MSL |
| 线程私有资源 | 堆 | 栈、寄存器上下文 |
| SQL NULL判断 | = NULL | IS NULL / IS NOT NULL |
| 哈希索引 | 支持范围查询 | 仅支持等值匹配 |
| 浅拷贝与深拷贝 | 浅拷贝复制指针指向对象 | 浅拷贝只复制指针,对象还是同一个 |
4.2 高频考点对应的刷题与看书思路
如果你准备笔试时不想漫无目的地刷,我建议按“教材+题库+真题”三层来备考。教材选王道考研系列或者严蔚敏的数据结构都行,重点是吃透课后题里关于概念辨析的部分。题库方面,牛客网有专门的校招真题模块,里面历年大厂笔试题非常全,可以按企业筛选、按知识点分类刷。我把京东的卷子刷完之后还会去刷其他大厂的同年代卷子,因为知识点高度重合,多刷一套等于把同样的基础再过一遍。
在刷题方法上,我强烈建议错题本用电子表格维护,至少记三列:知识点、错误原因、正确思路。错误原因这列特别关键,要区分是“概念没记住”还是“审题失误”还是“计算错误”。我自己统计过,真正的概念盲区只占30%左右,剩下70%都是审题和粗心。了解这个比例之后,考前最后一天我不再刷新题,而是把错题本从头翻一遍,把那些“审题失误”的题重点看一遍,考试时心底就有数了。
4.3 考前一周的复习节奏建议
最后一周不建议再做新题了,以查漏和保持手感为主。我的安排是这样的:前四天每天做一套完整的模拟题,严格计时90分钟,用手机倒计时,训练考场节奏。后三天回归基础,每天抽两小时把数据结构、操作系统、计算机网络、数据库四门的思维导图过一遍,不用细看文字,只要看到某个知识点能立刻说出“它考什么、常见的坑是什么”就可以过了。
考前一天晚上不要再熬夜刷题,早点休息。客观题考的是快速反应,睡眠不足导致的精神迟钝,足以让你在几道需要仔细计算的题目上栽跟头。我那年就见过考场里有人连IP地址的与运算都算错,大概率就是状态不行。
4.4 面试环节会怎么延续这套笔试
笔试只是第一关,它考出来的薄弱点,面试官大概率还会追问。比如笔试里错了死锁相关的题,面试官可能就会让你现场说说“怎么用资源有序分配法预防死锁”。所以笔试结束不等于万事大吉,考完当天把不会的题弄明白,其实是给面试做最好的准备。
那些笔试里没出现的知识点也不代表不用管,面试官很喜欢“笔试里的延伸”。比如你笔试里TCP握手答对了,面试官可能会继续问你“SYN Flood攻击是怎么利用三次握手的”。如果笔试答案正确但原理理解不透,这个追问就会露馅。我的观点是:校招笔试的客观题是记忆和理解的晴雨表,备考时要抱着“每一道题都能给面试官展开讲讲”的心态去学,笔试分数反而是次要的。
5. 写在最后的个人感受
笔试准备是一个人和自己较劲的过程。现在回头看2017年那套客观题(二),它考的知识点我后来在工作和跳槽面试里几乎都遇见过。底层基础这东西很奇妙,平时感觉不到它的存在,可一旦遇到线上问题、性能瓶颈、架构选型的时候,操作系统、网络和数据库这几块能不能顶上去,差距一下就拉开了。
如果你正卡在某些易错点反复犯错,别急着否定自己。我当年把快速排序最坏复杂度错了三遍才彻底记住,把TIME_WAIT和2MSL对应起来也花了不少工夫。聪明人用笨功夫,刷题这事没有捷径,但可以用对方法:先搞懂为什么,再动手练习,最后反复消化错题。
这套卷子你已经拿到了,接下来就是你自己的复盘时间。祝每一位准备校招的朋友都能在笔试这一关走得稳稳当当,拿到心仪的面试机会。