ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

2016京东研发笔试题复盘:从TCP握手到动态规划全解析

2026/8/30 10:51:34 拓冰建站 浏览量
2016京东研发笔试题复盘:从TCP握手到动态规划全解析 前几天整理移动硬盘翻到一份2016年京东研发工程师在线笔试题的做题记录。老实说那会儿我差2分没进面试后来花了一个周末把整套题重新做了一遍把每个选项为什么对、为什么错全部查了一遍。现在回头看这套题的价值早就超出了“能不能进京东”本身——它的题型设计和考点分布基本代表了当时一线互联网公司对研发工程师的通用能力要求。哪怕放到现在校招笔试的考点范围也几乎没有跳出这套题的框架只是难度和考察深度有所变化。适合读这篇内容的人主要有三类正在准备校招或社招笔试的研发岗同学想系统梳理计算机基础知识的开发者以及带新人的技术面试官。如果你是第一种建议别只把它当“古董题”看而是当一份知识诊断书来用。文章后面每一道题我都会把出题意图、正确解法和容易踩的坑讲清楚你看完可以直接照着复盘。1. 笔试全景2016年研发岗到底在筛选什么2016年前后京东的研发工程师在线笔试一般分为三个大块。第一块是通用能力测试包含逻辑推理、数字推理、图形推理和言语理解这部分很多技术同学容易直接忽略觉得跟写代码没什么关系。第二块是专业基础知识全部是客观选择题覆盖计算机网络、操作系统、数据结构、数据库、编程语言和Linux常用命令。第三块是两道在线编程题需要在限定时间内写出完整代码并提交运行判题系统会跑多个测试用例。整套题的时间一般不超过120分钟题目量很大几乎没有回头检查的时间。我记得当时做专业选择题的时候平均每题只有不到一分钟的思考时间。这意味着什么意味着很多题目考的不是你会不会而是你对这个知识点是不是熟练到“肌肉记忆”的程度。那些需要现场推导半天的题目在笔试环境下基本等于做不出来。1.1 一个容易被忽略的信号为什么先考行测通用能力测试放在第一关不是没有道理的。互联网公司的研发岗需要跟产品、运营、供应链、客服等多个角色沟通逻辑是否清晰、能不能快速理解别人表达的需求是工程师非常重要的软素质。行测题放在笔试第一关本质上是在用最低成本筛掉沟通成本高的人。这一点到现在很多公司还在沿用只是包装形式变成了“性格测试”或“场景题”。另外行测里的图形推理和数字推理考的是模式识别能力。这种能力和工程师日常做的事情有很强的关联——拿到一个从未见过的bug能不能快速从现象里归纳出规律再做假设验证。所以别把行测题当成走流程它背后确实有一些合理的筛选逻辑。1.2 从考点分布反推工程师能力模型仔细看专业基础部分的题目分布你会发现它重点考的不是“背得多”而是“理解得深”。网络部分常考TCP连接建立和释放的过程、IP地址与子网划分操作系统部分常考进程线程区别、死锁条件、页面置换算法数据结构部分常考二叉树遍历、排序算法的时间和空间复杂度、哈希冲突处理数据库部分常考索引失效、事务隔离级别。这些知识没有一个超出大学计算机课程的范围但出题人会在题目里设置很多“看起来对”的错误选项。举一个例子如果直接问“TCP三次挥手和四次握手的区别”大多数人能答上来。但题目换成“客户端发送FIN后进入什么状态服务端发送FIN前处于什么状态”就有人开始混淆TIME_WAIT和CLOSE_WAIT。这说明知识点不是孤立记忆的而是要放在完整的状态机里理解。所以做这套题的正确姿势不是刷题而是以题带点把每个选项背后的原理吃透。当年我的教训是刷了三遍题还是错同一个地方因为每次只是记了正确答案没搞懂错误选项为什么错。后来改成“每个选项都要写出解释”的方式效果完全不一样。2. 网络与操作系统选择题基础不牢地动山摇2.1 子网划分算得快的同学已经赢了一半当年有一道非常典型的题把 192.168.1.0/24 网络划分成4个大小相同的子网问每个子网能容纳多少台可用主机。很多人一看“4个子网”立刻把256除以4填了个64然后信心满满地选了下一题。这恰恰是出题人设置的陷阱。正确答案是62。原因很简单从 /24 借2位作为子网号子网掩码变成 /26主机位剩下6位。2的6次方是64但每个子网都要去掉网络地址和广播地址所以可用主机数是64减2也就是62。这个“减2”是子网划分题目里最经典的考点几乎每家公司的笔试都会出现。这类题目的解题要点可以总结成三步第一步看需要划分几个子网决定借几位主机位。4个子网需要借2位2的2次方等于4。第二步算出新的子网掩码也就是/26对应255.255.255.192。第三步用剩余主机位计算可用地址数先算2的6次方再减2。如果题目问“每个子网的网络地址是多少”常见的是192.168.1.0、192.168.1.64、192.168.1.128、192.168.1.192这四个。这个规律是每个子网步长为64也就是2的6次方。弄懂了步长计算不管怎么变花样都能快速算出来。2.2 TCP三次握手不要只背流程另一个高频考点是TCP连接建立过程。题目会给一个序列号场景问你确认号应该是多少。很多同学只背了“三次握手”四个字但笔试会具体到客户端发送SYN报文消耗一个序号服务端返回SYNACK消耗一个序号同时ACK的确认号是客户端序号加1客户端再发送ACK这个ACK如果不携带数据不消耗序号。举个具体例子客户端发送的SYN报文里 seq1000服务端收到后返回的SYNACK报文应该是 seq5000随意设的服务端初始序号ack1001。这个1001就是客户端下一个期望收到的序号。很多人会在这里出错把确认号写成1000因为在很多简化的讲解里“确认号等于收到的序号加1”但这里收到的是1000所以确认号是1001没毛病。问题出在有些人把SYN消耗的序号忽略了。我的建议是刷这套题之前先用抓包工具把一次HTTP请求的TCP握手过程完整看一遍把每个字段对应到三次握手报文里。看完之后再回来做题这类选择题基本就是送分题。理解SYN和FIN都要占一个序号是理解整个TCP状态机的基础。2.3 操作系统并发一道题讲透进程与线程操作系统部分最常考的是一道进程线程综合题比如问“进程和线程的主要区别是什么”。选项里通常会有一个“线程拥有独立的地址空间”很多同学看到就觉得对其实这句话是错误的——线程共享进程的地址空间独立的地址空间是进程的特征。题目还会设置一个干扰项说“进程是资源分配的基本单位线程是CPU调度的基本单位”这个才是标准表述。还有一道经典并发题两个线程同时对一个全局变量执行 i 操作i 的初始值是0各执行100次最终结果可能是多少。答案是2到200之间不是很多人以为的200。原因在于 i 在底层分成读、加、写三步两个线程如果交错执行某些加操作的结果会被覆盖。比如线程A读取了0线程B也读取了0两者都加1再写回最终结果是1等于两次自增只生效了一次。理解了这道题synchronized 和原子变量为什么存在就顺理成章了。如果题目继续追问用 volatile 修饰 i 能不能解决这个问题答案是也不能因为 volatile 只保证可见性不保证原子性i 这个复合操作依然不是线程安全的。这类题从表面考并发实际考的是对底层指令执行过程的理解。再看死锁。京东2016的笔试题很少直接问“死锁的四个必要条件是什么”而是给一个场景比如两个线程分别持有一把锁然后互相等对方释放锁问这种情况属于破坏了哪个条件或者如何避免。回答这类题目的关键不是背术语而是能画出线程和资源的等待关系图。只要环出现了死锁的隐患就存在。3. 数据结构与数据库那些年反复出现的考点3.1 二叉树遍历由遍历序列反推二叉树数据结构题里二叉树是绝对的大户。2016年前后特别喜欢考一种题型已知一棵二叉树的前序遍历序列和中序遍历序列问后序遍历序列是什么。这类题的解法是固定的前序遍历的第一个节点一定是根节点再到中序遍历里找到这个根节点的位置它的左边是左子树、右边是右子树然后递归处理下去。我拿一个简单例子说明前序是 ABC中序是 BAC那么根节点是 A中序里 A 左边是 B右边是 C所以左子树是 B右子树是 C后序就是 BCA。如果题目再复杂一些无非是子树规模变大递归思路完全一样。这里有一个常见陷阱如果只给前序和后序一般情况下无法唯一确定一棵二叉树因为无法区分左右子树。题目如果缺少中序序列一定要小心选项里那些“看似唯一”的答案。我在复盘时特意把所有遍历题整理成一套模板包括递归和非递归两种写法。非递归的后序比前序和中序难一些因为需要两个栈或者用逆序思路才能保证访问顺序。笔试虽然不直接考代码但面试环节几乎必问。建议你提前把三种遍历的非递归写法都跑通到时候不会卡壳。3.2 排序算法复杂度高频送分题也是高频丢分题排序算法的选择题看着简单却特别容易丢分因为出题人会换成各种问法。比如堆排序的平均时间复杂度是多少快速排序的最坏情况发生在什么条件下归并排序需要多少额外空间这不是背一张复杂度表就能应付的你需要理解背后的原因。快速排序为什么平均是 O(nlogn)因为理想情况下每次划分都能把数组分成大小差不多的两半递归深度是 logn每层需要 n 次比较。最坏情况发生在每次划分都选到最大或最小元素序列被分成1和n-1两部分递归深度变成n层每层还要做n次比较总复杂度就退化到 O(n²)。如果在已经有序的数组上每次都取第一个元素当基准就会触发这个最坏情况。额外空间方面最容易记混的是快排和归并。归并排序需要 O(n) 的辅助数组因为合并两个有序数组时必须临时存放结果。快速排序平均需要 O(logn) 的栈空间因为它递归的深度是 logn。搞清楚这些“为什么”比直接背答案可靠得多。面试官如果在笔试后追问排序也几乎总是从这些细节入手。3.3 数据库索引最左前缀原则为什么重要数据库几乎是必考模块京东的题目尤其喜欢考索引失效的场景。典型问题一张表有联合索引 (a, b, c)查询条件写成 where b1 and a2这个索引会不会生效很多人一看“b 在 a 前面”就认为失效实际上现代数据库优化器会先做等价改写把 a2 的条件挪到前面所以索引依然生效。但如果是 where b1 and c2完全没有 a 的条件这个联合索引就会失效。最左前缀原则的本质是联合索引底层的B树结构。B树排序的时候先按第一列排第一列相同的再按第二列排以此类推。少了最左列整个排序结构就失去了定位的起点所以索引失效。题目常通过“跳过中间列”来考这个比如 (a, b, c) 索引上执行 where a1 and c2只能用到 a 这一列来定位c 的条件只能在索引查找后过滤。这类数据库题做多了以后我总结出一个规律出题人很少直接问“B树是什么”而是通过索引失效、回表、覆盖索引这些实际场景来考。整理错题的时候把每个场景都过一遍比死记硬背SQL语法有价值得多。回表的意思是查到主键后再回主键索引查整行数据如果查询的列都包含在索引里就不需要回表这就是覆盖索引的意义。4. 编程题解题实录动态规划与边界条件在线编程题是整套笔试里最拉分的地方两道题一般覆盖两个方向一道偏动态规划或贪心一道偏字符串或模拟。下面我用当年出现频率最高的题目类型还原完整的思考过程。注意我不只是给答案还会讲清楚每一步的判断依据。4.1 动态规划题以“上楼梯”为例讲状态设计题目大意是一个人上楼梯可以一次跨1级、2级或者3级问到达第 n 级台阶一共有多少种走法。这个题很多人第一反应是写递归但直接递归会超时因为在计算 f(n) 时需要重复计算 f(n-1)、f(n-2)、f(n-3)而且 n 稍微大一点递归树就爆炸了。正确做法是动态规划。定义 dp[i] 表示到达第 i 级台阶的走法数那么 dp[i] dp[i-1] dp[i-2] dp[i-3]。初值需要根据题意仔细定义dp[0]1 表示站在地面不动这一种状态dp[1]1dp[2]2。计算顺序从3开始往后推一直算到 n时间复杂度 O(n)空间复杂度可以优化成O(1)只用三个变量滚动记录。这个题看起来简单实际提交时的边界很容易出错。n0 时应该返回1还是0不同的在线判题系统要求不一样有些测试用例包含0如果题目没有明确说明最好在代码里做一层防御。n 很大的时候结果会不会溢出如果需要取模一般题目会明确给出模数比如 1000000007如果没说用 long long 会保险一些。我当时还做过一个扩展版本如果每一步能跨的步数不是一个连续的集合而是一个给定数组 steps比如只能跨1级和3级那么状态转移方程就变成 dp[i] sum(dp[i-step] for step in steps if i step)。理解了基础版之后这个扩展版本就是加一层循环的事。动态规划题目刷到一定程度你会发现核心就两件事状态定义和状态转移方程。4.2 字符串处理题先想清楚再动手另一类常考的是字符串题目。比如给一个字符串要求按单词反转把 I am a developer 变成 developer a am I。这种题最稳的解法是两步反转法第一步把整个字符串反转成 repoleved a ma I第二步把每个单词内部再反转得到 developer a am I。这个方法的优点是空间复杂度O(1)只需要在原数组上做交换时间O(n)。手写时要特别注意空格处理单词之间是单个空格还是连续空格字符串开头和结尾有没有空格不同题目对这些细节的约定不同。如果题目没有明确说明可以先用最简单的方法按空格切分反转数组再拼接。这样虽然多用了空间但不容易出错。在笔试环境下先写出正确代码再在注释里写出优化方案往往比一上来就追求最优解法更稳妥。如果面试官追问“输入是一个字符数组而不是字符串”逻辑也一样只是你不能用 split 这类便利API必须手写单词边界判断。这类题不会考特别高深的算法重点考察工程实现中的细致程度。很多人栽在连续空格上反转之后空格数量不对用例直接不过。4.3 判题环境里的三个隐藏坑在线编程题最容易忽略的往往不是算法本身而是输入输出和边界处理。这里三个坑我当年都踩过输入输出格式。题目经常要求处理多组输入很多人代码逻辑没问题却没写 while (cin n) 这种循环读取导致只通过了第一组测试用例后面直接判运行时错误或答案错误。数据类型选择。C 的 int 和 long long 要提前想清楚。题目如果给出 n 的范围是 10^9数组下标或者累计结果就可能超过 int 上限再用 int 就会溢出输出一堆负数。全局变量污染。笔试判题不是只跑一次一个测试用例运行后全局变量的状态可能会影响下一个用例。所以能用局部变量就不要用全局变量用完了也要记得重置。这三个坑都不是算法问题但淘汰率不比算法题低。判题系统只看最终的通过用例数不会在意你算法想得多么精妙跑不过就是跑不过。5. 行测与逻辑题容易被低估的分数很多研发同学看不起行测部分觉得跟技术没关系随便勾选。但从通过率来看行测恰恰是被提前筛掉的重灾区。我当年就是因为图形推理花太多时间导致后面专业题没做完总分被拉下来。这个教训印象很深刻。5.1 图形推理找规律而不是猜答案图形推理常见的规律包括数量变化、位置旋转、叠加去同、对称性、封闭空间数量。比如一组图形中每个图形的封闭区域数依次是1、2、3、4那么下一个图形应该是5个封闭区域。这种题切忌盯着图形“找感觉”要在草稿纸上把数量、位置、对称轴数量这些要素列成数列。数字推理和图形推理本质上是同一类问题考的是模式识别。比如数列 2, 6, 12, 20, 30下一项是42因为相邻差是4, 6, 8, 10是二级等差数列。图形题也是一样把每个图的属性数字化之后问题就变成了数列题。这个方法一旦掌握图形推理的准确率会明显提升。5.2 言语理解画关键词还有一类言语理解题给一段产品需求描述问这段话的主旨是什么。技术同学容易犯的错是去选“看起来更专业”的选项但这类题的标准做法是找主题词和转折词。“但是”“然而”“实际上”后面往往是重点。选项里偷换概念、以偏概全、无中生有的都要排除。比如一段话说“当前系统吞吐量不足主要瓶颈在数据库层但单纯升级硬件不能解决根本问题需要优化索引和缓存”问主旨正确的选项一定是“需要通过索引和缓存优化来提升系统性能”。而“应该升级硬件”这种就是典型的错误理解。这种题做起来并不难难的是很多技术同学习惯性带入自己的技术判断而没有严格根据题干信息来选。5.3 行测做题顺序建议我的个人经验是先做专业基础题再做编程题最后回头做行测。原因是专业题和编程题分值高、确定性高会就是会不会就是不会。行测的推理题即使花很多时间也不一定能做对不如先保证确定性高的题目拿够分。时间分配上行测部分给自己留20到25分钟就够了不要恋战。拿不准的题先标记跳过去全部做完有剩余时间再回头琢磨。当年国考行测的时间分配逻辑也是同理——在拿不准的题上较劲是性价比最低的做法。6. 复盘与备考策略把一套题的价值榨干6.1 错题本的正确用法记录“为什么错”而不是“答案是什么”做完这套题之后我的复盘方式是每道错题都记录三列——错误原因、涉及知识点、正确的思考路径。比如“网络题错得多了原因是子网划分公式不熟”就把IP地址二进制转换练十遍“线程题错得多了原因是并发模型理解停留在概念”就去把同步器的实现机制看一遍。这个方法比重复刷三遍题有效得多因为每道错题都指向一个具体的知识漏洞。只记正确答案的话下次换个出题角度还是会错但把错误原因拆解成知识点之后你就能针对性地补课。我后来带实习生也采用类似办法让他们每周交一份错题分析一个月后基础抽查成绩提升非常明显。6.2 从真题反推知识体系刷完这套题你可以把题目涉及的知识点画成一张知识地图计算机网络TCP/UDP、IP地址与子网划分、HTTP状态码、DNS解析流程。操作系统进程与线程、死锁、内存管理、页面置换算法。数据结构二叉树遍历、排序算法、哈希冲突、链表操作。数据库索引、事务隔离级别、SQL优化、并发控制。编程语言内存管理、集合类底层结构、并发工具。对每个叶子节点去补一轮基础课。这套题最好的用法不是“模拟考试”而是“诊断书”。哪个分支最薄弱就优先补哪个分支。很多人复习时喜欢从第一章开始看教材这种方式效率很低以题带点缺哪补哪是更节约时间的备考方式。6.3 面试官会怎么追问笔试从来不是终点。很多面试官手里就拿着你的笔试结果针对你做错的题展开追问。如果你笔试题做错了但面试时能主动说出正确思路和当时的失误原因反而会加分最怕的是笔试蒙对了面试时一问三不知。所以我建议每道错题都准备一个“口头解释版本”用3句话讲清楚原理。比如子网划分那道题面试追问时你可以这样说“划分4个子网需要借2位主机位掩码从 /24 变成 /26剩余6位主机位减去网络地址和广播地址可用主机数是62。”这样既展示了计算能力也展示了表达能力。如果面试官继续追问“如果子网大小不一致怎么办”那就是VLSM的灵活应用你可以在白板上把每个子网的起止地址列出来。再比如TCP那道题被追问时可以主动说出SYN和FIN都消耗一个序号所以确认号是收到序号加1。面试官接下来大概率会问TIME_WAIT为什么是2MSL你如果能说出是为了保证最后一个ACK能被对方收到、同时让旧报文在网络中消失这一串追问就能顺利接住。最后再分享一个我自身复习中的体会京东2016这套笔试题最好的地方在于它没有偏题怪题全部都是计算机专业的基础知识只不过换上了电商场景的外衣。把这份题目彻底吃透你在面对其他互联网公司的笔试时也会更有底气。我在实际复习中把每道错题都整理成了“一句话解释”考前翻一遍只需要半小时但效果比临时抱佛脚刷新题好得多。整理错题时多花的时间最后都会变成面试现场的信手拈来。