2019年秋招那阵子小米的笔试几乎是身边同学都会投的一场。软件开发岗的笔试链接发下来之后点进去会随机抽到A卷或B卷我当时抽到的就是B卷。整套题做下来最大的感受是题型结构并没什么花活但基础细节挖得比想象中深。尤其是选择题里那些平时不以为然的考点稍不注意就掉进陷阱编程题反而中规中矩难度在LeetCode中等偏下。这篇文章不打算照搬题目而是结合当年B卷的考点分布和解题思路做一个完整的复盘。无论你想投小米还是其他互联网公司的软件开发岗这套备考逻辑都能直接用。1. 这套B卷到底在考什么题型分布与岗位画像1.1 为什么分A/B卷B卷是什么定位很多同学第一次参加大厂笔试时会好奇A/B卷到底有什么区别。从实际体验看A/B卷主要是为了防作弊题目顺序会有调整部分选择题和编程题也会做替换但考察范围和难度基本对齐。B卷并不是“备胎卷”或“补考卷”它在题型设置上跟A卷是同一套标准只是在具体题目上存在差异。软件开发岗的笔试定位很明确快速筛选出基础扎实、代码能力过关、能直接上手干活的人。所以题目不会考特别偏门的知识点但会在一眼看去“很基础”的题目里埋雷。1.2 全卷结构还原选择题、填空题、编程题、开放题根据当时B卷的体验和同学之间的复盘整套卷子大致分四块题型题数时长建议考察重点单选题约20题40分钟数据结构、操作系统、网络、数据库、语言基础多选题约5题10分钟概念辨析、边界条件判断编程题2-3题60分钟数据结构与算法、字符串处理、DFS/BFS开放/设计题1题10分钟系统设计思路、方案表述能力这里要提醒一个关键点多选题是按点计分的漏选和错选都会扣分。很多同学在单选部分做得顺手一到多选就犹豫结果选多了反而不得分。我的策略是除非特别确定否则宁可少选一个也别冒险。1.3 题量与时间分配别在第一题上死磕整套卷子的总时长一般在100到120分钟表面上看时间充裕但实际做起来选择题里的计算题和编程题都会吞时间。身边不少同学挂在同一个问题上在某个复杂多选或冷门考点上死磕了十几分钟导致后面编程题时间不够。我的建议是单选题平均每题控制在90秒以内遇到不会的先标记跳过多选题每题最多3分钟编程题按分值分配时间先把最容易拿分的题做出来再回头处理难题。这套策略在B卷上帮我稳住了节奏。2. 选择题里的专业课硬骨头数据结构与算法基础2.1 链表、栈与队列细节题的重灾区数据结构部分是选择题的绝对大头链表、栈、队列是必考基础但B卷考得比较“刁”的地方在于它不只是问“栈的特点是什么”而是给出一段具体操作让你判断结果。比如这道典型题一个栈的入栈序列为1、2、3、4出栈序列中不可能出现的是哪个选项。看上去是送分题但关键在于“边入边出”这种状态是否被考虑进去。很多同学脑子里默认入栈全部完成后再出栈于是把2、1、3、4这种合法序列误判成非法。遇到这类题老老实实在草稿纸上模拟一遍比凭直觉快且准。链表的考点也不局限于“单链表和双链表的区别”而是会延伸到实际场景。我记得B卷有一道题问“在已知某个节点指针的情况下删除该节点的最优时间复杂度是多少”。如果只背了“删除链表节点需要遍历找到前驱”就很容易选成O(n)。但题目给的是“已知该节点指针”在单向链表中确实做不到O(1)除非是交换后继节点值的取巧方式。这里就考察对“操作本质”的理解而非单纯记结论。2.2 二叉树与图的遍历递归还是迭代二叉树的选择题主要集中在遍历方式和性质计算上。前序、中序、后序、层序这些基础概念大家都熟但B卷会结合两种遍历序列反推二叉树结构比如给出前序和中序要求判断后序序列。这类题平时练过就不难没练过的话在考场上很容易慌乱。我的做法是拿到前序序列后第一个元素就是根节点再到中序序列中定位根节点左右两边就是左子树和右子树递归拆分即可。听起来是基础操作但很多同学在笔试时不愿意画图总想在脑子里完成递归结果十有八九出错。笔试题不是面试没人看你怎么算草稿纸该用就用。图的部分B卷更侧重于概念题比如“有向图和无向图的邻接矩阵对称性”“DFS和BFS的时间复杂度”等。这类题没有太多技巧把复杂度公式记清楚就行。需要注意的是用邻接矩阵表示图DFS和BFS的时间复杂度都是O(V^2)而用邻接表则都是O(VE)。这个点在选择题里反复出现。2.3 排序与查找复杂度对比不能只背结论排序算法是选择题的常青树但B卷很少直接问“快排的时间复杂度是多少”而是喜欢给一个特定场景让你选“最合适的排序算法”。比如“数据基本有序使用哪种排序算法效率最高”答案是插入排序或冒泡排序的改进版。又比如“要求排序稳定且时间复杂度为O(n log n)”归并排序就是最稳妥的选择。下面是我当时考前整理的一张对比表笔试前看一眼很管用排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性冒泡排序O(n²)O(n²)O(1)稳定插入排序O(n²)O(n²)O(1)稳定选择排序O(n²)O(n²)O(1)不稳定快速排序O(n log n)O(n²)O(log n)不稳定归并排序O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定查找部分则多考二分查找的边界条件和哈希冲突的处理方式。二分查找的题经常以“数组”“有序”“查找目标值”为关键词出现看起来简单但循环条件到底用left right还是left right每次更新边界是mid还是mid±1笔试时很容易差一点点就死循环。推荐的写法是统一用左闭右开区间能少很多边界烦恼。3. 操作系统、网络与数据库非科班最容易翻车的区域3.1 进程线程、死锁和内存管理这三大块基本是选择题里除数据结构外的第二得分区但对非科班同学来说也是翻车重灾区。原因很简单平时写业务代码根本接触不到这些全靠考前背而背的东西在考场上稍微变形就认不出来了。进程和线程的考点集中在区别与通信方式上。进程间通信方式有哪些、线程间共享哪些资源这些是高频题。B卷里有一道题让我印象很深问的是“多线程程序运行时哪些资源是线程之间共享的”选项里有堆、栈、代码段、寄存器等。错的不是一个两个——很多人以为栈是共享的实际上每个线程都有自己的栈而堆是进程内所有线程共享的。这类题就是考察对运行时模型的理解死记硬背容易翻车。死锁的四大必要条件互斥、持有并等待、不可剥夺、循环等待一定要背熟同时要能区分“预防”和“避免”的差异。预防是破坏四个必要条件之一避免则是在资源分配时通过银行家算法等判断是否安全。B卷往往会给一个具体场景问“哪项措施可以打破循环等待条件”答案一般是资源有序分配法。内存管理部分主要考分页、分段、虚拟内存、页面置换算法。LRU最近最久未使用是最常考的置换算法但要注意它和OPT最优置换算法的区别OPT是看未来LRU是看过去实际系统无法实现OPT。B卷有一道题问“给定一个页面访问序列计算使用FIFO和LRU时的缺页次数”这种题没有捷径只能一趟趟模拟。3.2 网络协议TCP和HTTP的细节题网络题在B卷里占比不小而且考察点非常集中TCP三次握手/四次挥手、TCP与UDP的区别、HTTP状态码、DNS解析过程。三次握手几乎年年考但B卷不喜欢直接问“为什么需要三次握手”而是会给一个场景判断。比如“如果只有两次握手可能会出现什么问题”答案是已失效的连接请求报文突然到达服务器导致服务器误以为建立连接并等待数据造成资源浪费。这里的关键是理解三次握手的本质是让双方都确认自己和对方的收发能力正常。TCP和UDP的区别也是必考题但别只背“TCP可靠、UDP不可靠”。B卷会更深入地考“TCP如何保证可靠传输”选项涉及序号、确认应答、超时重传、流量控制和拥塞控制。比如“TCP流量控制是使用什么机制实现的”答案是滑动窗口而不是拥塞窗口。这两个概念很多人混在一起笔试时看到“流量控制”和“拥塞控制”就发懵。HTTP状态码也值得专门过一遍2xx代表成功、3xx代表重定向、4xx代表客户端错误、5xx代表服务端错误。B卷里考过“301和302的区别”这俩都是重定向但301是永久重定向302是临时重定向语义不同浏览器的缓存处理方式也不同。这个点看起来小但在选择题里出现频率不低。3.3 SQL和索引查漏补缺的关键数据库题型以SQL语法和索引为主。SQL题基本都是“给出两张表查询某个条件下的记录”考察JOIN、GROUP BY、HAVING和WHERE的区别。记住一个核心点WHERE在分组前过滤HAVING在分组后过滤绝大多数同学栽在这上面。索引的考点集中在“哪种情况下索引会失效”。B卷的选项一般会给几个SQL条件让你选哪些用不到索引。最常见的失效场景包括对索引列使用函数或计算、使用LIKE模糊匹配且通配符在开头、对索引列进行隐式类型转换等。这些知识点不背还真不容易答全。事务的ACID特性也是高频考点尤其隔离级别和脏读/不可重复读/幻读的关系。B卷的题目一般会给一个“出现幻读的场景”问“当前事务处于什么隔离级别”之类的把四个隔离级别对应哪些问题背熟就行。4. 编程题实战复盘从读题到AC的完整思考过程4.1 字符串与数组类题目先模拟再优化编程题部分B卷的题量不算大但每道题都需要完整的思考过程。我记得有一道字符串题大意是“给定一个字符串找出最长无重复字符的子串长度”。这题在LeetCode上也有原题属于经典的滑动窗口问题。如果一上来就想最优解容易卡住。我当时的思路是这样推进的最简单的暴力解枚举所有子串逐个判断是否有重复字符时间复杂度O(n³)先确保思路正确。观察到子串的连续性可以用双指针维护一个窗口配合哈希集合记录窗口内的字符右指针不断向右扩展遇到重复字符时移动左指针时间复杂度降为O(n)。上机写代码时注意边界空字符串返回0字符串长度为1时返回1。C的参考写法大致是这样class Solution { public: int lengthOfLongestSubstring(string s) { unordered_setchar window; int left 0, right 0, ans 0; while (right s.size()) { if (!window.count(s[right])) { window.insert(s[right]); right; ans max(ans, right - left); } else { window.erase(s[left]); left; } } return ans; } };这道题想提醒的点是笔试时不要一上来就追求最优解先写暴力解把流程走通再逐步优化。很多同学为了省时间直接想最优解结果边界没处理好调试半天反而丢分。4.2 DFS/BFS类题目纸笔模拟比空想靠谱B卷通常还会有一道搜索类题目最常见的是岛屿数量或矩阵路径类问题。这类题的考点不只是算法本身还有对递归终止条件的把握。我遇到的题目是“给定一个二维网格其中‘1’表示陆地‘0’表示水域求岛屿数量”。思路很直接遍历每个格子遇到‘1’就计数加一然后通过DFS把同一座岛屿的所有‘1’都标记为‘0’。核心代码思路如下void dfs(vectorvectorchar grid, int i, int j) { if (i 0 || i grid.size() || j 0 || j grid[0].size() || grid[i][j] 0) return; grid[i][j] 0; dfs(grid, i - 1, j); dfs(grid, i 1, j); dfs(grid, i, j - 1); dfs(grid, i, j 1); }这道题容易出错的地方有两个。第一一定要先判断坐标是否越界再去访问grid[i][j]顺序反了会越界访问。第二使用网格本身来标记已访问避免额外开一个visited数组能减少空间复杂度。笔试环境里代码越精简越好调试。4.3 边界条件、复杂度分析和其他隐藏坑编程题除了算法本身还有一些经常被忽略的细节输入输出格式小米笔试用的是牛客网或赛码网系统有时需要自己处理多行输入。提前熟悉这些平台的输入输出模板不然写对了逻辑却拿不到分是最冤的。数据范围注意题目给出的n取值。如果n在10^5级别O(n²)的算法基本会超时如果n在10^9级别很可能需要用数学公式或二分凑答案。复杂度的分析过程笔试系统一般不要求你写复杂度说明但在代码注释里写清楚对后续检查有帮助。边界输入空数组、单个元素、全部相同元素等情况在写完代码后用测试用例过一遍。B卷的编程题整体难度在LeetCode中等偏下但不要因此掉以轻心。真正的坑往往在输入输出和边界条件上算法本身反而是相对稳定的得分项。5. 开放性设计题怎么回答才不像在背答案5.1 先有框架再有细节开放题是B卷里比较特别的存在常常出现在笔试的最后部分看上去没有标准答案但阅卷时对思路的完整性是有隐形标准的。如果只写一句“可以用Redis缓存”就结束基本等于没答。一个稳妥的回答框架是业务场景 → 数据量估算 → 核心模块拆分 → 关键难点 → 设计方案 → 可能的改进。比如设计一个短链接系统可以先假设每天新增100万条短链接一年就是3.65亿条存储上用关系型数据库存映射关系生成短码时避免用自增ID以防被遍历更稳妥的做法是用哈希值或雪花算法生成再配合缓存加速读取。这套框架的价值在于它让阅卷人一眼看到你具备“从需求到落地”的完整思维链路而不是只会堆技术名词。5.2 贴合小米业务场景来答当时B卷的开放题有一个特点场景会往小米的业务上靠比如智能家居控制、MIUI系统功能、消息推送等。如果你完全不理解这些业务场景很有可能答偏。我的建议是不管题目具体是什么先把“用户是谁、有多少并发、数据怎么存、延迟要求多高”这几个基本问题列出来。比如消息推送系统的设计要考虑设备在线状态、推送通道选择长连接还是厂商推送、离线消息的存储、失败重试机制等。把这些维度覆盖到即使方案不算最优也能体现出专业度。另外要注意开放题的答案不需要写代码但可以用简单的流程描述或关键接口定义来辅助说明。我当时用了三段式先说系统整体流程再列出核心模块职责最后指出这个设计的瓶颈以及如何扩容。这个回答逻辑帮我稳住了开放题的分数。5.3 开放题的时间控制很多同学在开放题上容易陷入“想写完美方案”的误区结果写出很长一段反而压缩了前面编程题的时间。开放题一般控制在10到15分钟比较合理重点是框架完整、思路清晰、关键点覆盖到位不需要把每个细节都展开。如果时间不够优先写核心模块和关键难点忽略过度细节。阅卷人更看重你是否具备系统级思考能力而不是你到底写了多少字。6. 秋招备考时间线笔试前一个月、一周、一天该干什么6.1 知识点排查表对照查漏补缺笔试前一个月不建议再开始啃新知识而是要系统性地排查自己的知识盲区。这里我整理了一份当时用过的排查表供你参考模块必考知识点自查情况数据结构链表操作、栈与队列、二叉树遍历、堆、哈希表是否熟练算法排序、二分查找、双指针、滑动窗口、DFS/BFS、动态规划能否手写操作系统进程与线程、死锁、内存分页、页面置换能否辨析概念计算机网络TCP三次握手/四次挥手、TCP与UDP、HTTP状态码能否说出细节数据库SQL基础、索引失效场景、事务隔离级别能否写出查询编程语言语言基础语法、内存管理、常见的库/API是否熟练排查的方法很简单找一个周末把每个模块常见的选择题刷30道正确率低于70%的模块标记为弱项下一周集中补。不要凭感觉判断“我好像会了”做题是唯一靠谱的检验方式。6.2 笔试前一周从刷题转向总结考前一周不要再大量刷新题重点转向总结和回顾。我当时的做法是把LeetCode高频题按标签分类每类挑3-5道重做一遍。把数据结构与操作系统的常见考点做成思维导图或笔记睡前过一遍。熟悉笔试平台的输入输出模板确保多行输入、字符串解析这类问题不会卡壳。考前一周最重要的是稳住状态。如果某一类题始终做不出来果断放弃把精力放在能稳定得分的题上。笔试是筛选考试不是竞赛拿到该拿的分数比攻克所有难题重要得多。6.3 笔试当天环境、时间和心态的细节笔试当天有一些细节容易被忽略提前确认电脑摄像头、浏览器、网络是否正常。小米笔试一般有在线监考设备问题可能导致无法进入考试系统。找一个安静的环境手机调成静音放远一点。开始答题后先浏览一遍所有题目对整体的难度分布做到心里有数。编程题如果卡住超过20分钟先跳过做后面的题等其他题做完再回头硬啃。我当时在B卷上遇到一道填空题卡了十几分钟果断跳过之后发现后面的编程题并没有想象中难反而追回了大量时间。笔试的节奏感很大程度上决定了最终成绩。7. 这套B卷复盘下来我最想跟你们说的事参加小米2019秋招软件开发的笔试已经过去挺久了但每次回看这套B卷都觉得它像一个很标准的“互联网公司软件开发岗基础能力测试样本”。它没有偏题怪题所有题目都在考纲范围内但恰恰是这种“看着都学过”的题目最能拉开差距。我后来帮不少学弟学妹做过笔试复盘发现一个普遍的规律拿到笔试题时慌的人不是知识储备不够而是没有形成稳定的答题节奏。选择题卡壳、编程题没有思路、开放题写太短或太长这些问题都跟平时刷题习惯有关。如果你现在正在备战秋招我建议你从今天开始每周至少完整模拟一次120分钟的笔试用真实的平台和计时器来练。不要每次只刷几道LeetCode就觉得自己在准备了。模拟笔试能帮你找到属于自己的节奏也能提前暴露你在时间分配上的毛病。最后再分享一个小技巧每次模拟完笔试后不要只看分数把所有错题按考察模块归类记录错误原因。坚持一个月你会发现自己对哪些内容吃得很透哪些内容一考就慌。然后再有针对性地补弱项效率会高很多。希望这份B卷复盘能在你的秋招路上少走一段弯路。