ARTICLE DETAIL

建站实战干货

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

小米秋招软件开发笔试复盘:基础考点、编程题思路与备考策略

2026/9/1 22:20:10 拓冰建站 浏览量
小米秋招软件开发笔试复盘:基础考点、编程题思路与备考策略 9月下旬的某天晚上我卡着点进了2021年小米秋招软件开发方向第二场笔试的在线考场。我之所以把这套题复盘专门写出来是因为它几乎是国内互联网大厂和硬件厂软件开发笔试的一个标准缩影选择题覆盖面广但不算偏编程题难度梯度拉得比较开整体非常考验“基础功是否扎实”和“能不能在有限时间内做出取舍”。当时和我一起投递软件开发方向的同学有不少人挂在编程题上不是不会写而是前面选择题磨太久到后面没时间调通代码非常可惜。这篇文章不会只粘贴题目答案而是把整场笔试拆开揉碎讲清楚它到底在考什么、每一类题目背后的知识点是什么、编程题的完整解题思路和代码怎么写以及复盘之后我总结出的备考路线。如果你正在准备大厂软件开发岗的笔试或者还在犹豫要不要刷题、刷什么题这篇内容值得你花20分钟看完至少能帮你少踩几个我踩过的大坑。1. 笔试整体结构与考察方向拆解1.1 题型分布与时间压力当时我拿到卷子后的第一感觉是题量不算变态但时间依然紧张。整套笔试大致分成两个大块一是计算机基础类选择题二是算法编程题部分场次还会穿插一两道系统设计或简答题。我记得整场笔试时长是120分钟选择题大概有30道左右编程题2到3道具体数量会随批次略有浮动。别小看这30道选择题它们的考察范围基本覆盖了计算机专业的核心课程数据结构、算法、操作系统、计算机网络、数据库、计算机组成原理偶尔还会冒出一两道C内存布局、Linux命令、设计模式相关的题。单道题的分值虽然不高但错太多直接影响笔试总评毕竟大厂笔试通常会设一道基础题正确率门槛基础题大面积失分的话编程题全对也可能被卡掉。时间压力主要来自两个方面。第一是选择题需要“快速判断”很多题不是算不出来而是算得慢比如考察进程调度算法、IP地址子网划分、数据库索引结构相关的计算题每道题控制在90秒内完成才算安全。第二是编程题需要“一次写对”在线笔试不像本地IDE那么顺手无法调试太久基本上第一道编程题要在25分钟内过掉第二道题才有充足时间优化和验证。1.2 科目权重说明了什么从我收集到的信息和我自己那场的感受来看小米软件开发方向的笔试更偏重“工程基础”而不是“竞赛算法”。选择题里数据结构、操作系统、网络这三块占比最高其次是数据库和计组算法题难度则介于LeetCode中等题和困难题之间极少出现那种需要灵光一现的偏难怪题。这个权重分配其实和硬件大厂软件岗的日常工作是吻合的你做嵌入式、驱动、中间件、系统开发天天要和内存、进程、网络、并发打交道这些基础科目就是吃饭的家伙。算法题考得不会太偏但也绝不是随便背几个模板就能应付的它更倾向于考“你会不会把数据结构和算法思想用到实际场景里”比如数组处理、动态规划、图的最短路径都是高频考点。所以如果你现在还在纠结“要不要把《算法导论》完整啃一遍”我的建议是不要。大厂校招笔试不会考论文级别的算法证明你需要的是把常见数据结构的操作复杂度背熟把高频算法题的套路练熟把操作系统和网络的核心概念搞透这些才是性价比最高的复习方向。2. 计算机基础选择题的高频考点与避坑思路2.1 数据结构与算法类选择题怎么秒判数据结构的选择题一般集中在几个固定的点上栈和队列的应用场景、二叉树遍历和性质、排序算法的稳定性和复杂度、哈希表冲突处理、图的最小生成树与最短路径。这些题说穿了就是“背结论 会推导”但有三个我反复踩坑的地方特别值得拿出来说。第一个是排序算法的稳定性判断。快速排序、堆排序、选择排序不稳定冒泡、插入、归并、基数排序稳定这个一定要记牢因为笔试不会直接问“哪个稳定”而是会换成“下列排序算法中哪些在平均情况下时间复杂度为O(n log n)且是稳定的”这种组合式考法特别容易让人犹豫。我就是在这种题上吃过亏当时选成了快速排序结果漏了归并排序白白丢分。第二个是二叉树相关性质的快速计算。n0 n2 1这个公式要变成条件反射满二叉树和完全二叉树的节点编号、层数换算也必须熟练。还有一点是赫夫曼树的构造考试不会给你特别复杂的节点但WPL带权路径长度务必亲手算一遍因为几个选项里的数值通常设计得非常接近心算出错的概率很高。第三个是哈希表。考察点主要是哈希函数构造、冲突处理方法开放定址、链地址法以及查找成功/失败时的平均查找长度计算。这类题没有捷径必须老老实实画表模拟。我建议在草稿纸上画一个清晰的表格列清楚每个关键字计算出的哈希地址、冲突次数避免重复计算。2.2 操作系统、网络、数据库与计组的经典题型操作系统选择题的高频区域几乎可以提前锁定进程与线程区别、进程状态转换、调度算法先来先服务、短作业优先、时间片轮转、多级反馈队列、死锁产生的四个必要条件与银行家算法、虚拟内存与页面置换算法OPT、FIFO、LRU、Clock、进程同步与PV操作。这里我要特别提醒一点银行家算法和页面置换是笔试最爱出大题式选择题的一定要把完整的判断流程写熟练因为这类题计算量不小如果没有提前练过当场推演很容易节奏崩掉。计算机网络部分主要围绕OSI七层模型和TCP/IP四层模型展开高频考点包括各层协议与设备的对应关系、TCP三次握手和四次挥手的状态迁移、TCP与UDP的区别、滑动窗口与拥塞控制慢开始、拥塞避免、快重传、快恢复、IP地址分类与子网划分、DNS解析过程、HTTP状态码含义。子网划分几乎是必考项遇到这类题一定要先把IP地址转成二进制再算网络号、广播地址和可用主机数不要凭感觉口算很容易在边界条件上栽跟头。数据库的选择题相对友好一些核心就是关系代数与SQL、范式判断与规范化、索引底层结构B树、事务ACID特性与隔离级别、并发控制锁、MVCC。范式的判断题是高频易错点我建议把1NF到BCNF的定义用“函数依赖”的角度重新理解不要死记硬背只要你能判断出“非主属性对码的部分函数依赖”和“传递函数依赖”大部分题目都能应付。计算机组成原理部分主要考数据的表示与运算原码、反码、补码、移码、IEEE 754浮点数格式、存储层次Cache、主存、虚存、指令流水线、中断与DMA。补码的加减法和溢出判断是高频基础题Cache的命中率与平均访问时间计算也经常出现。这类题需要一点数字敏感度建议考前把所有计算公式列成一张表每天过一遍。3. 算法编程题复盘两道典型题目的完整拆解3.1 第一题子数组相关问题的优化套路我印象里那场的编程题第一道是给定一个整数数组和一个目标值k要求找出和为k的最长连续子数组的长度不存在则返回0。这道题在LeetCode上有原题属于“前缀和 哈希表”的经典应用难度不高但非常考验你的优化意识。最简单的暴力解法是两层循环枚举左右边界时间复杂度O(n^2)对于 n 10^5 的数据范围一定会超时。核心优化思路是区间 [j, i] 的和等于 prefixSum[i] - prefixSum[j-1]如果它等于k那说明 prefixSum[j-1] prefixSum[i] - k。所以我们只需要遍历数组一遍用哈希表记录某个前缀和第一次出现的位置然后在当前 i 位置寻找 prefixSum[i] - k 是否在哈希表里如果在就用 i - firstIndex 更新答案。这里有一个非常关键的细节哈希表里存的必须是某个前缀和“第一次出现的位置”而不是最后一次出现的位置因为我们要找的是最长子数组。我第一次写这道题的时候不小心在哈希表里覆盖了旧索引导致求出来的答案要么偏短要么直接算错。这也是线上线下笔试很常见的失分点因为样例数据往往很弱跑一遍要么对要么错但如果是部分正确平台不会告诉你哪个用例挂了只能自己干瞪眼。C参考实现如下#include bits/stdc.h using namespace std; int longestSubarraySumK(vectorint nums, int k) { unordered_mapint, int firstPos; firstPos[0] -1; // 前缀和为0的位置设为-1方便计算从0开始的子数组 int prefix 0; int ans 0; for (int i 0; i nums.size(); i) { prefix nums[i]; if (firstPos.count(prefix - k)) { ans max(ans, i - firstPos[prefix - k]); } if (!firstPos.count(prefix)) { firstPos[prefix] i; } } return ans; } int main() { int n, k; cin n k; vectorint nums(n); for (int i 0; i n; i) cin nums[i]; cout longestSubarraySumK(nums, k) endl; return 0; }为什么要初始化为 firstPos[0] -1因为如果整个数组从0到 i 的和刚好等于k那么我们需要让 i - (-1) i 1这样才能计算出完整长度。这个边界处理是这道题最容易出错的地方。3.2 第二题动态规划状态设计的核心思路第二道编程题我记得是一道关于任务调度的题目场景大概是每个任务有一个持续时间和一个前置任务约束如果某个任务有前置任务必须等前置任务完成后才能开始假设当前系统有多个工作线程并行处理任务问完成所有任务的最短时间是多少。这种题本质上是带依赖关系的调度问题需要把“并行执行”和“依赖顺序”组合起来考虑。先说怎么建模。前置约束可以构成一个DAG有向无环图对于每个节点定义 dp[i] 为“完成节点 i 及其所有前置任务所需的最短时间”。因为多个任务可以并行执行所以完成一个任务的最短时间其实是“所有前置任务完成时间中的最大值 当前任务的持续时间”。用公式表示就是dp[i] max(dp[prev]) cost[i]这里必须取最大值而不能取和因为前置任务可以并行执行所有前置任务里最后完成的那一个决定了当前任务最早可以开始的时间。理解这一点是解出这道题的关键。实现上先用拓扑排序遍历所有节点一边遍历一边更新每个节点的 dp 值最后所有节点 dp 的最大值就是答案。代码框架大概长这样from collections import deque def solve(n, costs, prerequisites): graph [[] for _ in range(n)] indeg [0] * n for a, b in prerequisites: # b必须在a之前完成 graph[a].append(b) indeg[b] 1 q deque() dp [0] * n for i in range(n): if indeg[i] 0: q.append(i) dp[i] costs[i] ans 0 while q: u q.popleft() ans max(ans, dp[u]) for v in graph[u]: indeg[v] - 1 dp[v] max(dp[v], dp[u] costs[v]) if indeg[v] 0: q.append(v) return ans为什么用 dp[v] max(dp[v], dp[u] costs[v]) 而不是直接赋值因为一个节点的前置任务可能有很多个每个前置任务完成的时间不同必须取最晚的那个作为真正的开始时间基础。这个“取最大”和“累加”的区别就是动态规划状态转移中的核心辨析点笔试如果在这里写错样例过不去排查起来还不好找。3.3 在线编程的输入输出与调试技巧不少同学在本地IDE里写代码溜得很一上在线笔试平台就卡在输入输出上。软件开发方向的笔试通常要求自己处理输入尤其是C的cin/cout和Java的Scanner。我当时的建议是提前把模板写熟比如C用ios::sync_with_stdio(false); cin.tie(nullptr); 加速输入输出Python用sys.stdin.read()一次性读取然后split避免逐行读导致超时。还有一个容易翻车的点是在线笔试平台不允许查看所有测试用例很多用例设计得非常刁钻。比如数组长度为1、目标值等于数组唯一元素、所有元素为负数、数据范围接近int上限等。我建议每道题写完核心逻辑后花两分钟从头想一遍边界条件空数组、单个元素、重复元素、无解情况、数值溢出情况。这比检查语法重要得多因为在线判题只关心你的代码能不能通过所有隐藏用例。调试方面由于平台没有断点调试功能我的习惯是先用小规模数据在纸上推演一遍逻辑然后直接在代码里加打印日志查看关键变量的中间值确认无误后再删掉打印语句。千万不要一上来就凭感觉提交尤其是第二道编程题一旦提交失败重新编译、重新看题、重新排查的时间成本极高。4. 软件设计与方案题的作答思路4.1 这类题目到底在考什么小米软件开发笔试有时会夹带一两道“简答题”或“设计题”比如让你设计一个短链接系统、设计一个线程池、设计一个缓存淘汰策略、说明你对某个开源项目的理解。这类题目单看分值不高但它是面试官快速判断你“工程思维”是否到位的重要参考最好不要太潦草。设计题的核心考点不是“标准答案”而是你有没有一套完整的设计框架。以“设计一个线程池”为例一个合格的回答至少应该涵盖线程池的核心参数核心线程数、最大线程数、任务队列、拒绝策略、任务提交和执行流程、线程池状态管理、如何优雅关闭。如果你能把每个参数设置的“为什么”也讲清楚比如为什么核心线程数和最大线程数不能拍脑袋定而要结合任务类型是CPU密集型还是IO密集型来考虑这个回答就很容易拿高分。4.2 如何在有限时间写出高完成度方案在线笔试时间宝贵设计题不需要写出一篇论文我建议按照“需求分析 → 架构设计 → 核心模块设计 → 关键接口/伪代码 → 潜在问题与优化方向”这个顺序作答每个部分控制在3到5行把核心思路讲清楚即可。一个非常好用的策略是画ASCII流程图或者写伪代码。在线笔试系统通常支持纯文本作答你可以在答案里用缩进和箭头把流程串起来。比如设计一个缓存系统可以写“请求到达 → 查缓存 → 命中直接返回 → 未命中查数据库 → 回写缓存 → 设置过期时间 → 返回结果”。这种表达比大段文字更直观阅卷人一眼就能看出你的思路是否清晰。另外设计题千万别只写“用什么技术栈”如果题目没有特别要求不要堆砌“用Spring Boot Redis MySQL”这种话而要把重点放在为什么这样设计、容量评估怎么做、存在哪些瓶颈、如何扩展这些实际问题上。我当时做题时看到不少同学的设计题基本就是在写功能清单没有任何数据量评估和方案对比这种答案很难打动阅卷人。5. 复盘后的避坑清单与备赛建议5.1 考场上最容易犯的五个错误第一选择题时间分配失控。这是最普遍的问题。我见过有的同学在选择题上花了近70分钟最后编程题只剩20分钟基本只能交白卷。我的建议是选择题整体控制在一小时以内每道题一旦超过2分钟还没思路就先标记跳过全部做完后再回来看不要让一道难题毁掉两道必得分的编程题。第二编程题不写“思考过程”直接上手。很多在线笔试平台支持提交备注或代码注释但更重要的是动手写代码前先花3分钟想清楚数据规模、时间复杂度和核心数据结构。如果n是10^5你还在写O(n^2)的循环那基本等于浪费时间。第三忽视输入输出的边界条件。大厂笔试的隐藏用例往往包含极端情况比如非常大的整数、空串、单个节点、重复元素极多的数组等。请务必在写完后自查边界尤其是循环终止条件、数组越界、整数溢出这三种问题。第四动态规划的状态定义不清晰就开始写转移方程。状态定义错了后面全盘皆输。动笔前先用一句话把dp[i]的含义写下来再推导转移方程最后再写代码这个过程不能省。第五过度依赖本地IDE调试。在线笔试环境里没有“本地能跑、平台过不了”的说法平台上不过就是不过。平时刷题就应该尽量在模拟在线判题的环境里练习减少对IDE调试器的依赖。5.2 考后如何查漏补缺每场笔试结束后我建议立刻做两件事。第一把做错的每一道选择题都整理到一个错题本里不只是记录正确答案还要把错误原因写清楚比如“排序稳定性记混了”“子网掩码算错了一位”。第二把编程题重新在自己的IDE里完整写一遍并且把这一题的解题套路归入自己的模板库比如“子数组问题优先考虑前缀和”“依赖调度问题优先考虑拓扑排序DP”。我当时整理了一个自己的刷题优先级表参考价值比较大贴出来供你参考优先级知识点推荐练习方向高数组/哈希表/前缀和/双指针LeetCode双指针、前缀和标签下的中等题高链表/二叉树/递归二叉树遍历、最近公共祖先、链表反转高动态规划背包、最长子序列、编辑距离、区间DP高图论拓扑排序、Dijkstra、并查集中字符串处理滑动窗口、KMP、Trie中系统设计短链接、缓存、限流、消息队列5.3 投递节奏与多厂对比软件开发岗笔试最忌讳只盯着一家投递然后孤注一掷。我当时是在秋招窗口期同时投了多家不同类型的企业包括互联网公司、硬件厂商、云计算厂商和银行科技岗这样有几个好处第一不同公司的笔试风格差异很大有的重算法有的重基础有的重工程实践多考几次能够覆盖更全面的知识点第二笔试本身也是高强度练习每参加一场都能帮你发现一个知识盲区这是光刷题得不到的反馈。不过也要注意不要盲目海投导致精力分散。我个人的策略是把目标公司分成三档保底档、匹配档和冲刺档每一档投2到3家集中精力准备共性的核心知识点然后根据每家公司笔试侧重点做微调。比如投小米这类硬件厂商我会重点复习操作系统和内存管理投互联网公司我会把算法题优先级提高投银行科技岗我会多看看数据库和SQL优化。写在后面的一点经验整场笔试复盘下来我最深的感受是大厂软件开发笔试其实是一场“基础 速度 取舍”的综合挑战它在考察你是不是真的掌握了一个软件工程师日常必备的计算机功底也在考察你在压力下能不能做出合理的策略选择。基础不牢代码写得再花哨也没用速度太慢会的题也来不及做完不擅取舍就可能在小分题上耗死。如果你正在准备软件开发方向的秋招笔试我建议从现在开始每周至少安排两到三次完整的模拟笔试严格计时不查资料不做题外讨论完全模拟真实考试环境。刷题之外每天再抽30分钟过一个计算机基础知识点比如今天看死锁明天看TCP拥塞控制后天看B树索引积少成多比考前突击有效得多。最后再分享一个小技巧每次笔试结束后花10分钟在草稿纸上画一下整场考试的心智图——哪些题卡住、为什么卡住、下次遇到同类题应该怎么做——比单纯对答案有用得多。