十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

2017美团后台开发笔试题深度复盘:TCP、数据库与算法全解析

2017美团后台开发笔试题深度复盘:TCP、数据库与算法全解析 1. 这套笔试题的基本盘题型构成与考察方向先说一个背景2017年的美团秋招后台开发岗位的笔试还是典型的在线笔试模式选择题加编程题的组合。和现在很多大厂笔试动辄四道算法大题、两个小时不够用的情况不太一样那年的卷子给我的感觉是更看重基础知识的覆盖面算法题量没有后来那么夸张但一旦出现区分度非常明显。我当时拿到的卷子题型大致分三块单项选择、多项选择、编程题。选择部分覆盖计算机网络、操作系统、数据结构、数据库、Linux命令还有一小部分Java/C语言基础。编程题一般是两道到三道难度梯度拉得比较开第一道属于“热手题”最后一道才是真正拉开差距的。这套题对现在准备后台开发笔试的同学来说依然有很强的参考价值。原因很简单后台开发的核心知识栈不管是2017年还是现在无非就是网络、系统、数据结构、数据库这几大块。美团这套题的价值不在于题目本身有多新而在于它很典型地反映了互联网公司后台岗位“重基础、重原理、重实际场景”的出题思路。提示如果你正在准备互联网公司后台开发岗的笔试建议把2017到2020年间的真题都刷一遍。这些年份的题目风格更偏向基础原理考察不像近两年那样极端追求算法难度反而能帮你把知识体系打扎实。时间分配上我当年犯过一个典型错误在选择题上死磕。有一道关于TCP拥塞控制的题目选项设置得特别暧昧我在那题上耗了差不多八分钟直接导致后面编程题时间紧张。事后复盘正确的策略应该是选择题单题超过两分钟就标记跳过先把编程题的结构想清楚。整套选择题的难度分布并不是均匀的前面几道通常是送分题中间开始出现需要动笔计算的题最后几道反而可能是概念辨析题难度并不线性增长。从考察方向来看这套题的出题人很明显想把“理论基础”和“工程直觉”糅在一起。比如它不会直接问你“TCP和UDP的区别”而是给一个场景——视频直播场景下应该选哪个协议为什么。这种问法比背诵题更有区分度也是我在后文要重点展开的。2. 计算机网络题死记硬背过不去要懂场景2.1 三次握手与四次挥手不是画流程图就能拿分网络部分的选择题三次握手几乎是必考的但美团的出题方式不太一样。它不会让你选“哪两个标志位参与三次握手”而是给出一个状态序列问你客户端在收到SYNACK之后进入什么状态或者服务端在发送FIN之后、收到ACK之前处于什么状态。这种题乍一看是考状态名实际上考的是你对状态转移过程的理解。我推荐的复习方法是自己画一遍完整的TCP状态迁移图重点标注主动关闭方的TIME_WAIT状态。TIME_WAIT那块特别容易被追问为什么主动关闭方要等待2MSL美团当年虽然只在选择题里轻轻带过这个点但我知道很多人在面试阶段就栽在这里——说不清楚这2MSL到底在等什么。顺着这个思路往下说真正容易丢分的是四次挥手的变形场景。比如客户端发送FIN之后服务端还能不能继续发送数据很多人的第一反应是“不能”但正确理解是半关闭状态下服务端仍然可以发送数据直到它自己也发送FIN。这个点在选择题里经常以“以下说法错误的是”的形式出现。这里我建议你结合一条实际命令来验证自己的理解在Linux下用netstat -ant观察一个已关闭连接的端口你会发现很多连接长时间停留在TIME_WAIT状态。理解了状态机你才能理解为什么高并发短连接场景下会出现大量TIME_WAIT也才能理解tcp_tw_reuse这些内核参数到底在解决什么问题。2.2 TCP拥塞控制结合场景的变形题更考验人TCP拥塞控制的考法通常是给你一个发送窗口的变化曲线问你慢启动、拥塞避免、快重传、快恢复各自对应哪一段。这道题本身不难但2017年美团的选择题里有一道“加强版”它把拥塞窗口、接收窗口、发送窗口三者放在一起考问你实际发送窗口的大小取决于哪个。很多人会脱口而出“取决于拥塞窗口和接收窗口的较小值”这个没错但题目进一步问如果接收窗口一直不变拥塞窗口持续增长最终会发生什么这就涉及到接收窗口的“缓存上限”概念以及零窗口探测机制。如果只看《计算机网络》教材你大概率不会注意到这些工程细节但后台开发恰恰需要这种“协议实现”层面的理解。我的建议是复习TCP时不要只盯着教科书抽空读一读TCP协议栈的源码实现或者至少看一下tcp_output.c里对发送窗口的计算逻辑。这不是让你去背源码而是帮助你建立“协议是跑在代码之上”这一认知。很多题目所谓的“超纲”其实只是把工程实现中的边缘情况拿出来考。2.3 HTTP与HTTPS从状态码到安全握手的连环问答HTTP相关的选择题美团那套卷子里考得比较多的是状态码语义和HTTP请求方法。有一道题我现在还记得很清楚某个接口设计成幂等操作应该使用哪种HTTP方法选项有GET、POST、PUT、DELETE。这题表面考方法语义实际考的是幂等性概念。后台开发写接口时幂等性几乎天天都要面对所以这种题目对科班出身的人来说并不陌生。HTTPS的题目则倾向于考“SSL/TLS握手过程中客户端如何验证服务器身份”以及“对称加密和非对称加密分别用在哪个阶段”。前者直接关联数字证书与CA体系后者关联RSA与AES的配合使用。可以把这个过程类比成“先通过身份证验证你是谁再用一把双方约定的钥匙加密后续通信”这样理解起来会轻松很多。我不建议你在网络题上追求“背完所有协议”因为后台笔试的网络题范围实在太宽。更合理的策略是把TCP/UDP、HTTP/HTTPS、DNS、IP这五个核心模块吃透做到能清晰地用生活中的例子讲出“发生了什么、为什么这么设计”。这套真题里面绝大多数网络题都能用这个策略覆盖。3. 操作系统题进程线程、死锁与内存的经典组合拳3.1 进程与线程的区别要说到“共享”才够分操作系统部分的选择题第一梯队必然是进程与线程。美团那年的题里有一道多选题以下关于进程和线程的叙述哪些是正确的选项里藏着一个典型的错误表述——“线程是资源分配的基本单位”。正确答案里“线程是CPU调度的基本单位”这句很多人能选出来但还有一句“同一进程内的线程共享进程的地址空间”也容易被漏选。这就回到一个本质问题进程和线程最核心的区别到底是什么我的理解是进程是资源隔离和分配的基本单位线程是执行和调度的基本单位。进程拥有独立的地址空间、文件描述符表、信号处理方式线程则共享代码段、数据段和堆但各有独立的栈和寄存器上下文。这个知识点的另一个高频考法是问上下文切换开销。为什么线程切换比进程切换开销小因为线程切换不需要切换地址空间不会导致TLB缓存的失效。美团把这道题藏在了一个“下列哪种情况会导致CPU缓存失效”的题干里相当一部分人没反应过来。3.2 死锁从四个必要条件到实际分析死锁这个知识点几乎每年都有学校课程在讲但做对真题的人并不多。美团的题不会让你直接背四个必要条件而是给出一段加锁代码问你假设线程A持有锁1等待锁2线程B持有锁2等待锁1这是否构成死锁看起来很简单但题目会额外加一个条件如果两个线程都设置了超时重试机制死锁还会发生吗这个问题就上升到“死锁的预防与避免”层面了。超时重试并不能阻止死锁的发生只是通过回退操作解除死锁状态。真正的死锁避免算法是银行家算法它在资源分配之前先判断系统是否处于安全状态。我建议你把银行家算法的执行流程手写一遍因为选择题可能只考概念但编程题完全可能让你实现一个简化版本。还有一点容易被忽略操作系统笔试里的死锁题经常会和数据库里的锁冲突、分布式系统里的分布式锁混在一起出。美团那套题虽然没有出分布式锁的大题但在选择题里已经出现了“数据库死锁”的选项。这说明出题人默认你具备跨模块迁移知识的能力。3.3 内存管理虚拟内存与页面置换算法内存管理部分页面置换算法的考法相对固定给一个页面访问序列问使用FIFO、LRU、OPT时的缺页次数。这种题只要会模拟基本不会丢分。但美团有一道题稍微绕了个弯它问的是LRU算法的两种常见实现方式——链表哈希表以及数组实现——的时间复杂度对比。这道题的考点已经超出了“操作系统”本身跨到了数据结构设计。通过哈希表实现在O(1)时间内找到页面通过双向链表实现在O(1)时间内删除和移动节点合起来就是LeetCode 146题。如果你刷过这道题那美团这道选择题就是送分题如果没刷过现场推演一遍也不难。虚拟内存部分还容易考一个概念页面大小对页表大小和缺页率的影响。页面越大页表条目越少但内部碎片增加页面越小内存利用率越高但页表也越大。美团那年没出这个点但我强烈建议你把它搞懂因为这个思路在后来的笔试里反复出现几乎成了标准考点。4. 数据结构与算法笔试真正的分水岭4.1 选择题里的数据结构陷阱从栈应用到堆与优先队列后台开发笔试的选择题里数据结构很少直接考“什么是红黑树”而是结合具体操作考你。美团2017年的选择题有一道给定一个入栈序列问你以下哪个出栈序列是合法的。这类题按年“批发”但原理始终没变用栈模拟一遍任何时刻出栈的元素必须是栈顶元素。我统计过身边同学的错因大部分不是不会模拟而是没注意到题目中的“一次性入栈”与“边入边出”两种模式的区别。比如入栈序列是1、2、3、4、5问出栈序列3、1、2、4、5是否合法。如果你默认所有元素先全部入栈那就会误判正确做法是允许部分元素先入栈并出栈再让剩余元素入栈。堆和优先队列也是选择题常客。美团那年出了一道“在100万个数中找最大的100个数”的题选项给出了不同数据结构的组合。正确思路是用容量为100的最小堆而不是最大堆。每来一个新数和堆顶比较如果比堆顶大就替换掉堆顶并调整堆。这个思路考查的是对堆性质的灵活运用而不是单纯考察priority_queue的API。4.2 手撕代码真题回忆链表、字符串、动态规划当初的编程题第一道是链表类的“送分题”反转链表。但美团出了一点小变化——要求分别用迭代和递归两种方式实现并且分析两种方式的空间复杂度。这其实是在考验你是否真的理解递归栈的开销。迭代版空间复杂度O(1)递归版空间复杂度O(n)。如果你能在写代码的同时把这两点写清楚得分会很稳。第二道题大概是字符串处理给定一个只包含括号的字符串判断括号是否匹配。要求只能用O(1)的额外空间。这种情况下所有常见的“栈解法”都会因为空间复杂度不达标而失败需要利用一个计数器代替栈。这种题目看起来是在考字符串实际上是在考察你能不能从“栈”抽象出“计数”的等价关系。第三道题对我来说难度较高是一道动态规划最长公共子序列LCS。美团那道题没有直接给出两个字符串而是包装成“求两个文件路径的公共目录层级数”。本质上一样但多了从实际问题中抽象出模型这一步。建议你把LCS的状态转移方程从零推导一遍dp[i][j] dp[i-1][j-1] 1当字符相等否则dp[i][j] max(dp[i-1][j], dp[i][j-1])。4.3 算法复杂度分析的隐形扣分点编程题不光看代码能不能跑通很多时候还看复杂度分析。我见过不少同学代码写出来了但问复杂度时只说“大概是O(n)”这种表述在笔试里很吃亏。美团那套题的编程题界面下方专门留了“复杂度分析”的空格说明阅卷流程里这一项是有分数的。分析复杂度时要特别注意递归版的实现。比如递归反转链表表面上是O(n)时间但如果你忽略了递归栈的深度就会漏说空间复杂度。另一个常见的坑是字符串拼接在Java中使用可能隐式创建新对象导致看似O(n)的循环实际上变成O(n²)。笔试中如果允许建议用StringBuilder或char[]。从这套题来看后台开发的算法题并没有刻意追求LeetCode Hard而是更看重“能否把常见的数据结构与算法应用到工程场景”。这也符合美团笔试的一贯风格不会为了难而难但一定会在细节处检验你的理解深度。5. 数据库与Linux命令看似基础实则是送分与失分的分水岭5.1 SQL查询与索引优化写对容易写优难数据库部分的题目一般会先给两张表然后问你某个查询的结果是什么。美团2017年的SQL题里有一道典型的GROUP BY HAVING查询很多人在“WHERE和HAVING的执行顺序”上犹豫。我的记忆方法是WHERE在分组前过滤行HAVING在分组后过滤分组。这个顺序直接决定了SQL语句的正确性。接着是索引优化题给出一个查询条件WHERE age 20 AND name Alice问在哪些列上建立联合索引最合适。答案是应该把name放在联合索引的前列因为等值匹配优先于范围匹配。这涉及最左前缀原则与索引选择性。美团出了一道变体如果把等值条件和范围条件的位置互换索引还能否命中理解了联合索引的B树结构这个问题就迎刃而解。这类题给我的启发是数据库选择题不会直接考“什么是B树”而是通过索引命中的问题来反推你对B树结构的理解。复习时与其背索引规则不如画一遍B树的查找路径。5.2 事务与隔离级别ACID背后是并发控制数据库选择题的另一个高频区是事务。美团那套题有一道在可重复读隔离级别下一个事务两次执行相同SELECT查询结果是否一定相同很多人条件反射地答“是”但忽略了其他事务可能发生的插入操作——这就牵扯出“幻读”问题。不同隔离级别下哪些并发问题被解决、哪些仍然存在这是要花时间梳理清楚的。我通常建议用一张表来记忆事务隔离级别与并发问题的关系读未提交可能发生脏读、不可重复读、幻读读已提交解决了脏读但不可重复读和幻读仍可能发生可重复读解决了脏读和不可重复读但InnoDB在可重复读下通过间隙锁进一步解决了幻读问题串行化则全部解决。后台开发笔试里事务题很少只考理论通常会结合具体的锁机制。比如问当前事务执行UPDATE时对已存在的行和不存在但符合范围条件的行分别加什么锁这已经进入了Next-Key Lock的范畴。如果复习时间有限建议优先把“快照读”和“当前读”这两个概念搞清楚遇到大部分并发相关题目都不会被绕晕。5.3 Linux命令与网络排查后台开发日常素养的直接体现Linux命令的选择题看似简单却是我见过失分最严重的模块。美团那年考了ps -ef和netstat -tlnp的输出解读。题目本身不难但需要你能区分LISTEN和ESTABLISHED状态知道-l表示显示监听端口-n表示以数字形式显示地址和端口-p表示显示进程PID。还有一道关于awk的题目从日志文件中提取第2列和第5列并计算平均值。如果你没用过awk现场大概率懵掉。我的建议很直接把grep、awk、sed、find、top、ps、netstat这几个命令的常用参数在Linux环境里实际操作一次不要只看文档。它们不是面试八股而是后台开发每天都会碰到的工具。另外值得留意的是管道和重定向的细节。比如command1 | command2和command1 file 21前者考查进程间的数据传递后者考查文件描述符的指向。美团那年没出重定向的题但同一年其他大厂出了所以我在复盘时特意把它补进了自己的知识清单。6. 真题复盘与备考建议一套题怎么吃透才算够6.1 错题整理不只对答案要重建解题路径很多同学刷真题的方式是“做完对答案”然后记住答案就完事。这种方法对记忆型考点或许有效但对原理型考点几乎没用。我的做法是每道错题不仅记录正确答案还要写下“我当时为什么选错”和“正确思路的起点”。举个例子我在做数据库索引那道题时第一次把等值条件的列放到了联合索引第二列理由是“选择性高的列放前面”。复盘时我意识到这个逻辑适用于单列索引的选择但当查询条件同时有等值条件和范围条件时联合索引的列顺序应该优先保证等值条件的列在前面否则范围条件会让后续索引列失效。把这类“错因”记录下来比抄十遍正确答案更有价值。因为笔试考的不是你记住了什么而是你在陌生题目面前能否复用已有的推理框架。把错因归纳成几条“我容易踩的坑”考前半小时扫一眼比临时抱佛脚背知识点管用得多。6.2 用笔试真题反向训练面经一套题两种用法一个容易被忽视的技巧是笔试真题不仅用于刷题还可以当作面试题的素材库。美团这套选择题里几乎每一道都可以被面试官拿出来做引申提问。比如TCP拥塞控制那道选择题如果放在面试里面试官大概率会接着问什么是AIMD快重传和快恢复的触发条件是什么拥塞窗口和接收窗口冲突时以哪个为准所以我的建议是在刷完一套真题后尝试“角色反转”把自己当面试官把每道选择题改编成三个追问。这个方法能帮你同时准备笔试和面试效率非常高。我当时备考时把2017年美团这套题整理成了一份“追问清单”在模拟面试时反复用效果很不错。模拟面试还有一个隐形好处锻炼你在时间压力下的表达能力。笔试编程题要求写出完整可运行的代码而面试手撕代码要求边说边写。两者看似不同但对“代码组织和边界条件处理”的要求完全一致。把笔试题里的代码修改成可现场讲解的版本是双赢的准备方式。6.3 横向对比同年度其他大厂真题找到共性与差异单独刷一套真题容易陷入“只见树木不见森林”。我建议把美团2017年秋招后台开发的真题与同期百度、阿里、腾讯等公司的后台笔试题放在一起对比。你会发现网络、操作系统、数据库、算法这四个模块是所有公司的共同重点差异主要体现在出题风格和偏好的编程题类型上。美团当年的题目给我的整体感觉是基础题占比高偏门题少编程题难度递进合理。相比之下有些公司更爱考察数学推理有些公司更爱出大数据相关场景题。横向对比的意义在于你可以判断自己更适合哪个方向的岗位也能更精准地分配复习精力。如果你现在才开始准备我建议按这个优先级来先刷过去三年的真题把考点分布统计出来再按照高频考点逐个击破。对于低频但基础的考点比如Linux命令、HTTP状态码这些不需要花大量时间但要保证见过、不陌生。7. 最后的小技巧把错题变成你的模拟卷按照惯例分享一个我实际用过且很有效的方法不要只做真题还要“改造”真题。把做错的题目换一个选项描述、换一个数值、换一个场景条件再做一遍。比如美团那道TCP拥塞控制的题目原题问慢启动阶段拥塞窗口如何增长。我把它改成如果发生超时重传阈值和拥塞窗口分别会被设置为多少如果发生快重传又是什么变化这两个问题的答案是不同的前者是直接把拥塞窗口降为1阈值降为当前拥塞窗口的一半后者是拥塞窗口和阈值都降为当前拥塞窗口的一半然后进入快恢复。把一道题改成三道题来练你对知识点的理解深度会明显不一样。另一个技巧是“限时重练”。原题做完隔两周再拿出来做一遍只看错题限定自己在题目对应时间的一半内完成。这个方法能检验你是真的掌握了原理还是短期记忆在起作用。我当年用这个方法把一套真题反复用了三遍每次都能发现新的理解盲区。2017年美团的这套后台开发笔试真题放到今天来看虽然有些年份了但它考察的底层知识框架并没有过时。你不需要为“题目是不是太老”而焦虑反而应该庆幸这些基础原理类考点恰恰是性价比最高的复习方向。
返回列表