尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

小米2020校招笔试全解析:计算机基础与算法备考指南

小米2020校招笔试全解析:计算机基础与算法备考指南 先交代一下背景这份“小米2020校招软件开发工程师笔试题一”如果你现在拿出来看会发现它考察的东西其实一点都不过时。2020年正好是各家大厂把校招笔试从“筛简历”转向“筛基础”的分水岭小米这套题出的相当有代表性覆盖了数据结构、算法、操作系统、计算机网络、C/Java语言基础还有少量场景题。它不考偏题怪题也不搞脑筋急转弯核心就一句话你的计算机基础功到底扎不扎实。这篇文章我打算不按“逐题给答案”的方式写那样你背完就忘换个题型照样懵。我更想帮你拆清楚的是这套题背后的考察逻辑是什么、每类题型到底在测什么能力、解题时的思考路径应该长什么样以及如果你想拿它当备考素材该怎么刷才最有效率。无论你是正在准备校招的应届生还是工作两三年想查漏补缺的开发者这篇都能给你一些可落地的参考。1. 小米2020校招笔试题的整体考察逻辑1.1 笔试的定位不是筛“做过多少项目”而是筛“计算机基础是否牢固”很多人对校招笔试有个误解觉得笔试就是考算法、考LeetCode谁刷得多谁就赢。但以我这些年参与校招面试和出题的经验来看笔试真正想干的事情是用最短的时间、最客观的方式判断你值不值得进入面试环节。项目经历可以包装简历可以美化但笔试是实打实坐在那里一个小时到一个半小时靠真功夫说话的。小米这类硬件互联网双轮驱动的公司软件开发工程师的需求量很大从手机系统底层到MIUI应用层从IoT设备嵌入式到云端服务岗位方向非常多。校招笔试不可能为每个方向单独出题所以它一定考的是所有软件开发岗位共同的那部分底层能力代码功底、算法思维、系统理解、网络基础、语言特性掌握程度。这套2020年的笔试题题型分布大致是选择题约30-40分、编程题2-3道约60-70分。选择题覆盖了C/Java语法、数据结构、操作系统、计算机网络、Linux常用命令等编程题则集中在字符串处理、数组操作、二叉树遍历、动态规划这些高频考点上。为什么这样设计我个人的理解是选择题用来快速测“知识面”编程题用来测“代码落地能力”。知识面决定你能不能听懂面试官在说什么代码落地能力决定你进来之后能不能干活。这两个维度缺一不可——有些人知识面很广但代码写得稀烂进来之后连需求都实现不了有些人代码写得飞起但基础概念一团浆糊遇到线上问题连排查方向都没有。1.2 从行业热点反推考点风向嵌入式、移动端与软件流程管理如果你把搜索热词里那几个方向——嵌入式软件开发、移动软件开发、ASPICE软件开发流程——和小米的业务线放在一起看会发现这套题其实藏了不少“私货”。小米的IoT生态链产品线非常庞大从手环到扫地机器人从智能音箱到平衡车里面跑的全是嵌入式软件。所以它的校招笔试题里操作系统相关的内容占了不小的比重而且不是单纯考概念更偏向并发、锁、内存管理、Linux命令这些嵌入式开发每天都要打交道的东西。ASPICE是汽车行业软件开发的流程标准小米后面造车整个团队对软件工程规范化的要求直线提升。这也反映在校招笔试里——代码风格、变量命名、边界处理、注释习惯这些都是隐性考察点。同样的逻辑两道编程题都AC了但一个代码写得整洁规范、一个写的乱七八糟面试官是能通过代码风格看出你的工程素养的。移动端软件开发的热度就更不用说了Android开发是小米的立身之本。所以语言基础部分C和Java基本是平分秋色偶尔还会带一点Kotlin。JVM内存模型、GC机制、HashMap实现原理这些Java高频考点在这套题里出现的概率非常高。所以备考小米也好备考其他大厂也好千万别只闷头刷LeetCode。你需要把操作系统、计算机网络、语言基础这三个方向拉通复习尤其是操作系统里的进程线程、锁、内存管理基本属于必考内容。这套题的难度曲线其实挺有意思选择题里藏了不少两三个选项看起来都对的陷阱题编程题则是一道比一道门槛高第一道让你热身第二道开始上强度第三道直接拉开差距。这种设计不是小米独创但小米2020这套题把梯度控制得比较好既能筛出基础扎实的人又不至于全员被劝退。2. 核心题型拆解与解题思路2.1 数据结构与算法程序员的“内功心法”算法题在校招笔试里占的比重最大这已经是行业共识了。小米2020这套题里算法题主要集中在字符串、数组、链表、二叉树和动态规划这几个大方向上。先说说字符串和数组。这类题看似简单其实最容易踩坑。比如“字符串去重”“数组去重”“字符串反转”“最长公共前缀”这类题目第一反应可能是暴力法但笔试的时间复杂度限制会卡掉很多O(n²)的解法。面试官真正想看的是你用哈希表、双指针、滑动窗口这些技巧把时间复杂度压到O(n)。举一个典型的例子求“最长无重复字符子串”。暴力解法是枚举所有子串再逐一检查时间复杂度高达O(n³)笔试里一定会超时。用滑动窗口加哈希表记录窗口内字符位置一次遍历就能解决时间复杂度O(n)。别看这只是一个小技巧的差距它反映的是你有没有主动优化算法的意识。然后是二叉树题。这类题几乎是每场校招笔试的标配因为二叉树的遍历前序、中序、后序、层序、深度计算、路径查找、最近公共祖先等问题既能考察递归思想的掌握程度又能考察数据结构的理解深度。小米2020这套题里有一道层序遍历的变体要求按层输出每层的平均值或者是Z字形遍历。这类题的核心在于利用队列实现广度优先搜索同时在每一层的边界上做文章。动态规划是拉开差距的关键题目。背包问题、最大连续子数组、股票买卖问题、编辑距离这些经典模型都是校招笔试的高频题。动态规划题有两个关键点一是状态定义二是状态转移方程。很多同学一看到动态规划就头大其实它跟数学归纳法非常像——你只要把dp数组的含义定义清楚把转移方程推出来剩下的就是写代码的事了。题型高频考点核心技巧复杂度要求字符串最长无重复子串、最长公共前缀滑动窗口、哈希表O(n)数组两数之和、三数之和、合并区间双指针、排序O(n)~O(n²)链表反转链表、环形链表、合并有序链表递归、快慢指针O(n)二叉树层序遍历、最近公共祖先、路径总和BFS、DFS、递归O(n)动态规划背包问题、股票买卖、最长递增子序列状态转移、滚动数组O(n)~O(n²)我个人的建议是刷题时不要只盯着AC更要想清楚每道题的“最优解为什么是最优”。比如双指针能解决的问题为什么它比暴力穷举好快慢指针为什么能找到链表的环这些“为什么”想明白了笔试时遇到变形题才能举一反三。2.2 操作系统与并发不要死记硬背要理解设计动机操作系统是校招笔试的另一座大山。小米2020这套题里操作系统相关的题目主要覆盖进程与线程、调度算法、死锁、内存管理、锁机制这几个板块。很多同学复习操作系统的方式是背概念——“进程是资源分配的最小单位线程是CPU调度的最小单位”“死锁的四大条件是互斥、持有并等待、不可剥夺、循环等待”。背这些当然没错但笔试题目不可能只让你默写概念。它更常考的是这些概念在实际场景中的应用。比如它会给你一个场景多个线程并发访问一个共享计数器问你用synchronized和用volatile有什么区别这就不是背概念能答对的了。这里的核心考点是Java内存模型——synchronized保证的是原子性、可见性、有序性volatile只保证可见性和有序性不保证原子性。原子性靠的是锁机制可见性靠的是内存屏障。再比如进程和线程校招笔试特别爱考“两者的区别”和“各自的使用场景”。进程之间是独立的地址空间线程共享进程的地址空间。所以在多进程编程里通信得靠IPC机制管道、消息队列、共享内存、套接字在线程编程里通信只需要通过共享变量但随之而来的就是数据竞争问题需要靠锁来保护。内存管理也是操作系统模块的常客。虚拟内存、页面置换算法、分段分页这些概念不光笔试会考平时排查线上问题也会用到。比如你写代码时遇到OOM内存溢出如果理解JVM内存模型里的堆、栈、方法区、直接内存的区别定位问题就会很快。操作系统这块我给的建议是不要干啃教材试着把它和生活场景结合起来理解。进程和线程的关系就像一家公司和公司里的员工——公司有独立的办公地址地址空间员工共享公司的办公场地线程共享进程内存但员工干活的时候如果有两个人同时改同一份文件就会出问题数据竞争所以需要申请写文件权限加锁。2.3 计算机网络从输入URL到页面渲染的完整链路网络基础题在校招笔试里的出现频率也很高。小米2020这套题里网络相关的考点主要是TCP/UDP、HTTP协议、DNS解析、三次握手和四次挥手。这一部分最典型的考法就是“从浏览器输入URL到页面显示中间经历了什么”。这道题基本上是把网络协议栈串起来考DNS域名解析把域名转成IP地址建立TCP连接三次握手发送HTTP请求如果是HTTPS站点还需要TLS握手服务器处理请求返回HTTP响应浏览器解析HTML、CSS、JS构建DOM树渲染页面连接关闭四次挥手这道题面试官很爱问笔试选择题也爱考因为它覆盖了DNS、TCP、HTTP、浏览器渲染这四大块知识点。答好了说明你对整个网络体系有完整的认知答不好说明你的知识是碎片化的。TCP三次握手为什么要三次两次行不行这是另一个高频陷阱题。答案是两次不安全客户端发送SYN、服务器回复SYNACK之后如果客户端不回复确认服务器无法确认客户端是否收到了自己的SYNACK。如果只有两次握手服务器可能一直等待一个已经失联的客户端造成资源浪费。三次握手本质上是一个双方都确认“你发我能收、我发你能收”的最小往返次数。四次挥手的过程也经常被问到。它比三次握手多一次的原因在于TCP是全双工的——每一方的关闭都需要单独确认。客户端发送FIN表示我这边数据发完了服务器回复ACK表示我收到了但服务器还有数据要找客户端发等服务器数据发完之后再发送FIN客户端回复ACK这才算彻底关闭。HTTP协议这块重点要分清HTTP 1.0、HTTP/1.1、HTTP/2.0的差异。HTTP/1.1默认开启持久连接支持管线化请求HTTP/2.0引入了多路复用、头部压缩、二进制分帧。这些特性题直接决定了你对现代网络架构的理解程度。2.4 C/Java语言基础内存模型、面向对象与异常机制语言基础是校招笔试题中最“送分”也最“要命”的部分。说它送分是因为这些知识点只要复习过就能答上来说它要命是因为很多同学在准备笔试时把精力全放在算法上语言基础反而成了短板。C方向高频考点包括指针与引用的区别、const的作用、static关键字的作用、虚函数与多态的实现原理、内存分配方式栈上、堆上、全局区、构造函数/析构函数调用顺序、深拷贝与浅拷贝。其中虚函数的实现原理是必考题。C的多态是靠虚函数表vtable实现的——每个包含虚函数的类都有一个虚函数表对象内存布局的第一个位置通常是指向虚函数表的指针vptr。当调用虚函数时程序通过vptr找到vtable再从vtable中取出对应的函数指针进行调用。这个过程在编译期无法确定所以叫动态绑定。Java方向高频考点包括Java内存模型堆、栈、方法区、程序计数器、本地方法栈、GC机制与垃圾回收算法标记-清除、标记-复制、标记-整理、HashMap实现原理数组链表红黑树、ArrayList与LinkedList的区别、synchronized与ReentrantLock的区别、和equals的区别。HashMap的实现原理是Java笔试的“钉子户”。它的底层结构是数组加链表JDK 1.8后引入红黑树通过key的hashCode计算索引位置发生哈希冲突时用链表树化后是红黑树解决。为什么是红黑树而不是二叉搜索树因为红黑树是自平衡的即使在最坏情况下插入、删除、查找的时间复杂度也能保持O(log n)不会退化成链表的O(n)。异常机制也是Java笔试的高频点。受检异常checked exception和运行时异常runtime exception的区别是什么哪些异常必须捕获或抛出自定义异常应该继承哪个类这些问题看起来零碎但实际工作中写业务代码时经常遇到。语言基础这一块建议以“面试官可能会追问”的标准来复习不要只记表面概念。比如你说“HashMap是线程不安全的”那面试官一定会追问“那线程安全的Map有哪些”答案是HashTable和ConcurrentHashMap“ConcurrentHashMap的实现原理是什么”分段锁/CAS操作。一层层追问下去才是真正考察你有没有掌握到这个知识点的内核。3. 实战演示三道高频笔试题从读题到AC3.1 字符串类题目最长无重复字符子串这是LeetCode第3题也是校招笔试出现频率最高的一道题之一。题目描述很简洁给定一个字符串找出其中不含重复字符的最长子串的长度。def length_of_longest_substring(s: str) - int: left, right 0, 0 max_len 0 window set() while right len(s): # 当前右指针指向的字符不在窗口内时加入窗口 if s[right] not in window: window.add(s[right]) max_len max(max_len, right - left 1) right 1 else: # 当前右指针指向的字符在窗口内时移动左指针直到移除重复字符 window.remove(s[left]) left 1 return max_len解题思路拆解这道题最核心的思考是“滑动窗口”。你可以把窗口想象成一块可以伸缩的玻璃左边界是left右边界是right。右边界不断向右扩展把新字符纳入窗口当遇到重复字符时左边界向右收缩把重复的那个字符“挤”出去。为什么用集合而不是列表因为集合的查找时间复杂度是O(1)适合判断字符是否在窗口内。为什么时间复杂度是O(n)因为left和right各自最多遍历整个字符串一次整体是线性复杂度。常见错误有些同学会把max_len的更新写在窗口调整之后导致漏掉特殊情况。实际上max_len需要在每次窗口扩大后立即更新因为窗口扩大代表找到了更长的不重复子串。如果写在else分支里就可能漏掉一个字符都不重复的情况。进一步思考如果字符串中不只包含字母而是包含所有ASCII字符甚至Unicode这个解法依然有效。如果题目改成“最多允许两个重复字符”就要用哈希表记录每个字符的出现次数而不是集合。这就是变式题的考察思路。3.2 二叉树类题目二叉树的层序遍历题目描述给定一个二叉树返回其按层序遍历得到的节点值即逐层地从左到右访问所有节点。public ListListInteger levelOrder(TreeNode root) { ListListInteger result new ArrayList(); if (root null) { return result; } QueueTreeNode queue new LinkedList(); queue.offer(root); while (!queue.isEmpty()) { int levelSize queue.size(); ListInteger level new ArrayList(); for (int i 0; i levelSize; i) { TreeNode node queue.poll(); level.add(node.val); if (node.left ! null) { queue.offer(node.left); } if (node.right ! null) { queue.offer(node.right); } } result.add(level); } return result; }解题思路拆解这道题的核心是广度优先搜索BFS 队列。思路是这样的先把根节点入队然后进入循环每次循环先记录当前队列的大小也就是当前层的节点数然后只处理这么多节点——把它们全部出队值存入当前层的列表同时把它们的左右子节点入队。这样循环结束时result里就是一个按层分好的所有节点值。这里有一个关键点为什么要用int levelSize queue.size()先记录这一层的节点数因为如果不记录你在处理节点时又会不断往队列里加入新的节点这个for循环就永远走不完。所以必须先用变量把当前层的大小快照下来。变式题如果要求Z字形遍历第一层从左到右第二层从右到左第三层从左到右……只需要在把level加入result时反转一下即可。这种变式题在校招笔试里更常见因为出题人会在基础题上加一点变化来区分“背题的人”和“真的会的人”。3.3 操作系统与并发多线程交替打印这类题目在笔试编程题中不算多但在面试手撕代码环节是高频题。小米2020这套笔试题中虽然没有直接出这道题但并发相关的选择题出了好几道而且这种类型的题目最能体现候选人系统底层理解能力和工程能力。这里我补一道经典的交替打印题属于并发编程的经典入门题目描述创建两个线程一个线程打印奇数1、3、5、7、9另一个线程打印偶数2、4、6、8、10要求交替输出1、2、3、4、5、6、7、8、9、10。public class AlternatePrinting { private static final Object lock new Object(); private static int count 1; private static final int MAX 10; public static void main(String[] args) { Thread oddThread new Thread(() - { while (count MAX) { synchronized (lock) { if (count % 2 0) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(奇数线程: count); count; lock.notify(); } } } }); Thread evenThread new Thread(() - { while (count MAX) { synchronized (lock) { if (count % 2 1) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(偶数线程: count); count; lock.notify(); } } } }); oddThread.start(); evenThread.start(); } }解题思路拆解这里面的核心是“wait-notify机制”。线程在发现当前不该自己执行时调用wait()主动让出锁并进入等待队列执行完自己该干的事之后调用notify()唤醒对方。注意wait()和notify()必须在同步代码块或同步方法中调用否则会抛出IllegalMonitorStateException。踩坑提示这个写法有一个经典错误——用if而不是while来判断条件。上面的代码我用的是if这在只有两个线程的简单场景下没问题但如果线程数量变成三个以上就一定要用while做条件判断否则会出现“虚假唤醒”的情况。为避免这个隐患面试时要直接写成while这样即使面试官追问“你这个wait条件有没有问题”也能从容应对。4. 备考策略与踩坑经验4.1 时间规划别把战线拉太长也别临时抱佛脚校招笔试准备时间规划非常关键。我见过太多同学大二就开始刷LeetCode刷了两年刷了800道题结果笔试该挂还是挂——因为他只追求数量每道题看一遍题解就过了不做总结不复盘。我推荐的节奏是如果从现在开始准备每周保持70%的时间刷算法30%的时间过基础和系统知识。算法刷题每天保持2-3道新题同时每周固定抽一天回顾本周错题。系统知识复习不要贪多每天抽40分钟到1小时看一个专题比如今天看操作系统死锁明天看计算机网络TCP握手用表格或者思维导图把知识点串起来。考前一个月进入模拟模式每周找出一整个晚上限时1.5小时模拟真实笔试环境做一套完整题目训练自己的时间分配和应试心态。4.2 刷题方法论质量大于数量重复大于求新很多人刷题陷入一个误区一定要刷别人没刷过的题才有成就感。实际上校招笔试的题型高度重复考点就是那么多翻来覆去变着花样考。你真正需要做的是把经典题型练到形成了肌肉记忆。我自己常用的刷题方法是“三遍法”第一遍拿到题先想5-10分钟不管能不能想出来逼自己写一版解法哪怕是暴力解。第二遍看题解理解最优解的思路然后关掉题解手写一遍优解直到能一次性通过全部测试用例。第三遍过一周左右重新做这道题检验自己是不是真的掌握了。如果还能顺利写出来这道题才算真正属于你了。这一步之所以重要是因为笔试环境非常考验熟练度。你坐在考场里看到一道题如果还要现场推演各种情况时间一定不够用。但如果你在平时已经把这道题训练到了“手比脑子还快”的程度那一分钟之内你就能开始写代码。4.3 笔试环境适应从IDE到在线OJ的切换这是很多同学在校招笔试中折戟的原因也是不用写代码不会遇到的坑。平时你用本地IDE写代码代码提示、自动补全、调试器全都有写起来非常顺畅。但校招笔试用的是在线OJ系统只有一个简陋的代码编辑框没有代码提示没有调试器连编译报错都写得模模糊糊。所以考前一定要花时间适应在线编程环境。至少提前两周每周做2-3次在线OJ练习用牛客网、LeetCode的模拟笔试功能强制自己在没有IDE辅助的情况下完成题目。平时刷题时也刻意关掉自动补全练习手写完整代码。另外一个很实际的建议是笔试时先预览所有题目从你最有把握的题开始做。编程题通常有2-3道分值有高有低如果卡在一道难题上不起身后面简单的题分也丢了总分大概率不理想。我习惯是先把所有题目快速看一遍标记出简单题先拿保底分再花剩余时间攻坚难题。4.4 易错点与常见问题速查常见问题原因分析解决方法数组越界没考虑边界条件空数组、单元素数组写代码前先列出边界用例手动跑一遍整数溢出中间运算超过int范围使用long或对结果取模空指针异常没判断null情况访问对象前先做判空死循环while循环条件写错或没有终止条件给循环加个计数器必要时用调试器复杂度超标使用了O(n²)甚至O(n³)的暴力解法先想数据范围再定算法复杂度输出格式错误没有按题目要求打印多个空格或换行仔细阅读输出描述特别是英文题面这几个坑我在实际笔试中基本都踩过。尤其是数组越界这个看起来很简单但在紧张的考场环境下特别容易忽略。后来我养成了一个习惯每做一道题先花30秒写出这道题的所有边界条件空输入、单元素、最大长度、负数、重复元素再开始写代码。这30秒看起来是“浪费”实际上帮你省掉了大量调试时间。还有一个小技巧是善用注释。在线OJ的代码编辑框不支持调试器但支持注释。写代码时在关键逻辑处加上注释不只是给阅卷人看更是帮助自己理清思路。如果你写着写着发现逻辑混乱了回看注释就能很快找到哪一步出了问题。5. 从2020到当下这套题的备考价值在哪里很多人可能会问都这么久了这套2020年的笔试题现在看还有意义吗我的答案是有而且意义不小。互联网技术面试有一个有意思的特点核心考点非常稳定变的只是包装形式。2020年考两数之和2024年考三数之和本质都是用哈希表或双指针降低时间复杂度2020年考二叉树层序遍历2024年考二叉树锯齿形遍历本质都是BFS加一层逻辑处理。基础的数据结构、核心的算法思想、底层的操作系统原理这些不会因为年份变化而改变。整套2020年小米笔试最大的价值是它把软件开发工程师需要掌握的基础能力完整地扫描了一遍。你如果能把这套题吃透那你对其他大厂的校招笔试题也会有很强的适应能力——因为考点是通用的只是出题风格略有差异。另外从这套题里你还能看出小米这家公司对软件开发工程师的期待既要能写代码又要理解系统既要懂算法又要有工程意识。这不仅是小米的要求也是整个行业对软件工程师的基本要求。你未来的职业发展无论是做业务开发、底层开发还是架构方向这些基础能力都是绕不开的基石。回到开头那句话笔试筛的是基础。而基础这个东西恰恰是所有人花时间都能补上的。差别只在于你愿不愿意花时间、用对方法。
返回列表