ARTICLE DETAIL

资讯详情

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

2015小米实习笔试回顾:基础题与手写代码的筛选逻辑

2015小米实习笔试回顾:基础题与手写代码的筛选逻辑 1. 2015年那个夏天的笔试现场和现在的笔试有什么不同如果你有过备战互联网大厂实习的经历一定对笔试这种筛选方式不陌生。但2015年的小米暑期实习笔试和今天你在牛客网上定时开考、摄像头监考、自动判分的在线笔试完全是两个物种。那年我刚好经历了这场考试现在回头看这套题透露出的信息量远比考不考得过要大得多。先说背景。2015年小米正值巅峰期手机销量国产第一生态链概念刚火起来实习岗位的竞争激烈程度不亚于正式校招。当时小米的笔试主要分两种形式一种是和牛客网合作在线笔试另一种是线下宣讲会结束后现场发卷子手写答题。我参加的是线下场次一个能容纳两三百人的阶梯教室坐得满满当当发卷子的时候监考人员反复强调手机全部关机不允许查资料不允许讨论。现在你可能觉得这不是废话吗线上笔试不也这样。但手写和在线答题的体验差异极大尤其是算法题你在IDE里敲和在答题纸上写完全是两种思路。当年没有那么多刷题平台也没有LeetCode中文站大部分人的训练方式就是《剑指Offer》加王道考研数据结构狠一点的会刷POJ和HDU的专题。再说出题风格。2015年的笔试题有一个非常鲜明的特征基础极其基础但基础到大多数人答不上来。它不考你最新的框架、不考分布式、不考你简历上的项目而是考那些你觉得自己会、但真让你写又写不出来的东西。比如Java的HashMap底层实现、Android的Handler消息机制、进程和线程的区别、TCP三次握手为什么不是两次。这些问题放到今天依然是八股文但2015年的时候它们恰恰是区分用过和真正理解的分水岭。还有一个年代特征题目中混合了相当比例的智力题和数学题。现在的技术笔试几乎全是算法题加选择题智力题已经很少见了但2015年那会儿智力题是大厂笔试的标配。小米的这套题里就有烧绳子计时、倒水称重这类经典问题。说实话这些题放到现在的面试场景里很多候选人会觉得莫名其妙但放在当时它的考察逻辑其实是成立的——在计算机基础普遍薄弱、培训机构和网课还不普及的年代智力题是快速判断一个人思维是否敏捷的廉价方式。所以这篇文章我打算从一套可以公开聊的2015年小米暑期实习笔试题目出发逐类拆解它考了什么、为什么这么考、背后的筛选逻辑是什么以及如果你现在要备战类似的大厂笔试有哪些东西是过了这么多年依然没有变的。不敢说我的回忆完整还原了原卷但结合当年一起笔试的同学和后来流传的牛客网面经核心考点基本是能对上的。2. 从真题分布看考点版图基础、思维、手写三块拼图2.1 试卷的宏观结构三小时四类题型先说整张卷子的结构。2015年小米暑期实习笔试卷子我记得大概分四块选择题、填空题、智力题、编程题。考试时间三小时题量不小选择题大概二十道左右填空题七八道智力题三四道最后有两道编程大题。总分记不太清了比例大概是选择和填空基础分占大头编程题是拉分项智力题属于你答不上来别人也答不上来的区分题。当时小米的岗位分得很细有Android开发、iOS开发、后端开发、前端开发、测试开发、算法等。不同岗位的笔试试卷不完全一样但部分基础题是共用一套的。我考的是Android方向所以后面聊的题目会偏这个方向但Java基础、数据结构、算法这些绝对是所有技术岗共通的。选择题覆盖的知识面非常广从Java语法细节到操作系统死锁从计算机网络到数据库索引再到Linux常用命令甚至还有一两道关于UML类图和设计模式的题。这就是典型的摸底测试看你大学四年到底有没有系统学过计算机核心课程。填空题则偏向输出结果类比如给一段多线程代码问输出什么、给一个类的继承体系问字段初始化顺序这类题没有蒙的机会不会就是不会。智力题通常放在选择和填空之后作为承上启下的过渡。编程题在最后通常都是白纸手写要求写完整可运行的代码还得分析时间复杂度和空间复杂度。2.2 选择题里的基础素养考题选择题虽然占比大但题目本身的难度其实不算高真正难的是知识面太宽总有你盲区里的知识点冒出来。我印象比较深的几类第一类是Java基础。2015年正是Java 7到Java 8过渡的时期笔试题还停留在Java 7的语法体系上。常考的有和equals的区别String池的经典陷阱、HashMap和Hashtable的区别前者线程不安全、允许null键值、ArrayList和LinkedList适用场景随机访问vs频繁插入删除、异常处理中finally块的执行时机。这些知识点放到今天还是八股文里的常客但在2015年它们是实打实的工作基础——那时候Android开发主语言就是JavaJava基础不牢写出来的代码就是灾难。第二类是操作系统。进程和线程的区别这是必考的死锁的四个必要条件也是高频考点互斥、持有并等待、不可剥夺、循环等待。还有一道我记得很清楚给了四个进程的到达时间和服务时间算平均周转时间。这题本身不难但手算特别容易错如果你没真正理解短作业优先调度算法和先来先服务的区别很容易在细节上翻车。第三类是计算机网络。TCP的三次握手和四次挥手是必考的但考法很有意思不是直接问你为什么是三次而是给你一个状态转换的场景问当前处于什么状态。还有一类常考的是HTTP协议状态码的含义比如301和302的区别、403和404的区别。2015年移动互联网正火HTTP连接复用和Keep-Alive的概念也开始出现在选择题里。第四类是Linux和数据库。Linux常考的是文件权限chmod 755是什么意思、管道命令、grep的用法。数据库常考的是SQL语句的执行顺序、索引失效的场景、内连接和外连接的区别。这些知识点对于2015年的实习岗位来说属于你必须会但不一定天天用的内容考它们是为了确认你没有知识盲区。2.3 填空题里最不起眼但最见功力的部分填空题比选择题更让人头疼。选择题至少还有选项可以排除填空题完全是凭记忆和理解的硬功夫。这里我特别想说的是字段初始化顺序和静态代码块这一类题。Java里类加载和实例化的执行顺序在当时是公认的易错点。给你一个父类子类继承体系父类和子类各有静态代码块、构造代码块、构造方法问创建子类对象时输出什么。答案是父类静态代码块 → 子类静态代码块 → 父类普通代码块 → 父类构造方法 → 子类普通代码块 → 子类构造方法。这个顺序一旦记错整个输出就错了。现在你可能会说这有什么好考的但在Android开发里理解类加载顺序直接关系到Application和Activity的初始化逻辑还真不是纯八股。还有一类填空题是给一段多线程代码问输出结果。比如有个共享变量被多个线程修改问你最终的值是多少。这类题考察的是对synchronized和volatile的理解。2015年是Android Handler机制讨论最热烈的时候面试官出多线程题的核心目的是确认你是否理解线程同步的基本原理因为你后面做Android开发异步任务无处不在线程安全问题躲不掉。填空题的阅卷标准比选择题严格得多答案不对就是不对没有中间地带。所以三小时下来很多人不是不会做而是时间被选择和填空耗掉了大半最后编程题反而成了垫分题。2.4 智力题当年大厂笔试的标配现在几乎绝迹智力题这部分值得单独拿出来聊聊因为它最能体现2015年的时代特征。我印象里的题有烧一根不均匀的绳子总共需要一个小时如何用它来判断半个小时这个题的解法是同时点燃绳子的两端烧完就是半个小时。关键在于理解不均匀意味着不能用长度的比例来判断时间必须借助燃烧方向来加倍燃烧速度。另一个经典是有10个瓶子其中9瓶装的是正常药丸每颗重1克1瓶装的是毒药丸每颗重0.9克只称一次如何找出毒药瓶解法是把瓶子编号1到10从第i号瓶取出i颗药丸称总重量用理论上应有的重量55克减去实际重量差值是0.1克的多少倍就说明第几号瓶是毒药瓶。这题考察的是编码和信息论的思想本质上就是二进制编码的应用。这些题目在2015年的大厂笔试里非常常见不光是小米腾讯、百度、阿里的笔试题里也有类似的身影。有人觉得这些题和工作无关是纯粹的智力筛子但从公司的角度来看它们确实能筛掉一部分基础不牢、思维混乱的人。因为这类题的解法往往需要你跳出惯性思维找到问题的本质特征。不过后来的笔试题趋势变化也很明显。随着牛客网和LeetCode的普及刷题成为规模化行为智力题的区分度越来越低因为只要刷过题这些题就是送分题而没刷过的人现场想很难想出来。到2017年之后大厂笔试基本就全面转向纯算法题了智力题从此退出历史舞台。所以2015年几乎算是智力题在技术笔试里最后的辉煌期。3. 技术大题详解Java、Android、操作系统和网络到底考了什么3.1 Java必问的HashMap和并发2015年的考察深度比现在浅但更实用2015年的Java题目还没有卷到今天这种程度。那会儿HashMap的底层实现还是数组加链表红黑树的引入是Java 8之后的事情而2015年大多数笔试答案还停留在数组加链表这个层面。考法也很直接HashMap的put方法流程是什么Hash冲突怎么解决HashMap和Hashtable的区别有哪些我当时答题的思路很朴素先讲数组结构再讲通过hash计算下标然后讲冲突后用链表解决。放到今天这显然不够深入但2015年的评分标准就是看你能不能把主干讲清楚。现在回头看这段经历我意识到那个年代对实习生的要求是能干活、不闯祸而不是深入研究过底层源码。你只要理解HashMap不是线程安全的知道多线程环境下要用ConcurrentHashMap就已经超过大半候选人了。不过有一道Java题让我印象特别深刻是一道关于String不可变性的题目。题目大概是String s a b c;会创建多少个对象这道题表面上是考字符串常量池实际上是在考编译期优化。答案是如果a、b、c都是字面量常量那么编译器在编译阶段就会直接计算出abc运行时只会在常量池里查找或创建一个abc对象而不是创建三个中间对象。但如果a、b、c是变量那就是在运行时执行多次字符串拼接会创建StringBuilder和多个中间String对象。这道题考察的知识点一直到今天依然是Java面试的高频点因为它涉及JVM、编译原理和日常编码习惯三个层面。3.2 Android题目生命周期和Handler是永远绕不开的两座山Android方向的笔试题最有代表性的就是Activity生命周期和Handler消息机制。2015年Android开发正处于从2.x到5.x的迭代期Activity还是绝对的核心组件Handler也还没有被协程替代这两个知识点是必须烂熟于心的。Activity生命周期的考法通常是这样A页面跳转到B页面B是普通Activity从按下跳转按钮到B页面完全显示A和B各自经历了哪些生命周期回调答案是A执行onPauseB依次执行onCreate、onStart、onResumeA再执行onStop。如果B是透明主题的Activity那么A只会执行onPause不会执行onStop。这类题只要把生命周期那张流程图背熟基本不会出错但如果只背图不理解一旦遇到旋转屏幕、HOME键、来电打断这些特殊场景就很容易出错。另一道高频题是Handler导致的内存泄漏。场景是在Activity里创建一个HandlerHandler里面持有了Activity的引用然后发送一个延迟消息。如果这时用户退出Activity但延迟消息还没执行完毕会发生什么答案是Activity无法被GC回收导致内存泄漏。解法是在onDestroy里移除所有消息回调handler.removeCallbacksAndMessages(null)或者将Handler定义成静态内部类用WeakReference持有Activity的弱引用。这道题在2015年是妥妥的加分题因为它考察的是一个人是否具备内存意识而不只是会调用API。还有一道关于Android四大组件的选择题问哪个组件不能作为服务在后台长期运行。答案是Activity因为Activity必须有一个可见的界面它被完全遮挡时可能会被系统回收。而Service、BroadcastReceiver、ContentProvider都可以在后台运行。这道题本身不难但它考察的是对Android组件设计意图的理解——为什么要有Service它和普通Java线程的区别是什么如果理解了Service的设计初衷是让没有界面的任务在系统中有一席之地这道题就不会答错。3.3 操作系统和网络从会背书到会推导的差距操作系统和网络的题我挑两个考得最有水平的讲讲。第一个是死锁。2015年很多笔试题喜欢考系统中有m个同类资源n个进程每个进程最多需要w个资源问系统不会发生死锁的充分条件是什么。经典的解法是用鸽巢原理推导当每个进程都拿走了w-1个资源如果此时系统还有至少1个空闲资源就一定能打破死锁。所以条件是m n * (w - 1) 1。这道题有意思的地方在于它不只考察你死锁的定义还考察你是否能推导出那个临界条件。死锁的四个必要条件背下来不难但把这个公式推出来需要真正理解资源分配的过程。第二个是TCP三次握手。现在你看到三次握手肯定觉得很基础但2015年的考法很刁钻不是问你为什么三次而是给你一个场景——如果客户端发送的SYN包在网络中滞留了很久服务端收到了并回了SYNACK但客户端已经超时重传了新的SYN这时会发生什么答案是服务端会为旧的SYN建立一个连接但由于客户端已经因为超时而放弃了这次连接它收到服务端回应的SYNACK后会发送RST包重置连接服务端释放对应资源。这道题考察的是对TCP状态机、超时重传和RST机制的综合理解光背诵三次握手流程是答不上来的。网络部分还常考一道关于子网划分的题。给你一个IP地址和一个子网掩码问网络地址是多少、广播地址是多少、可用的主机数量是多少。这类题的特点是计算简单但容易出错特别是当你需要把IP和子网掩码都转成二进制然后逐位与运算的时候。2015年VLSM和CIDR的概念已经普及但考还是喜欢考最基础的分类地址比如一个/26的子网能容纳多少个可用主机。答案是64减2等于62个。这种题没有技巧只能老老实实地算。4. 算法编程题手写代码是硬门槛白纸上的代码比你想的更诚实4.1 当年编程大题的高频类型链表、二叉树的天下2015年的算法题风格和现在LeetCode的题型重叠度很高但有一个明显的区别难度相对较低。现在的暑期实习笔试Medium难度是标配偶尔会出现Hard题2015年的时候只要你能把Easy到Medium的题解出来基本就算过了。我印象里那年常考的题型有单链表反转、链表找环入口、两个链表的第一个公共节点、二叉树的前序中序后续遍历尤其要求非递归、二叉树的最大深度、判断一棵树是否为二叉搜索树。这些题放到今天都是入门级别的但在当年因为大家刷题量普遍不大能完整写出链表反转的就已经是少数了。链表反转这道题之所以经典是因为它考察的是指针操作的基本功。迭代解法需要三个指针prev、cur、next交替推进递归解法需要理解先反转后面的再让当前节点的下一个节点指向自己。很多人在白纸上写链表反转总是写乱最常见的问题是忘记保存next指针导致指针丢失。我当年还在迭代解法上栽过跟头因为循环终止条件写错了多走了一步导致链表成环。这种错误在IDE里很容易发现但在白纸上你甚至没有编译器帮你报错。另一道高频编程题是二叉树的层序遍历。2015年的时候层序遍历还不是什么热门题但现在回头看它是考察队列这种数据结构的极好载体。解法是用一个队列辅助每次把当前层的节点全部出队再把它们的左右孩子入队。层序遍历比前中后序更能体现一个人对广度优先遍历的理解因为它把BFS的思想具象化了。4.2 从写得出到写得对白纸手写代码的评分密码白纸手写代码和在线编辑器有个巨大的区别在线编辑器有语法高亮、有自动缩进、有编译器提示而白纸上什么都没有。你写出的代码必须靠人眼去读所以逻辑清晰、变量命名规范、边界条件完整这些软素质会直接影响阅卷人的评价。我后来作为面试官参与过校招笔试阅卷想告诉你一个真实情况阅卷人看每个人的代码时间不会超过十分钟而且首先看的就是边界处理。你的主流程写得再漂亮如果忘记处理空链表、空树、n0这些边界情况评分会直接降档。再一个容易被忽视的细节是时间复杂度分析。题目要求写完之后分析你的算法复杂度很多人直接忽略这一步。但其实这道送分题才是区分度所在如果你能在代码旁边清楚地写出时间复杂度是O(n)、空间复杂度是O(1)并且分析得门儿清说明你不是背的代码而是真的理解了自己的解法。我自己的经验是答编程题的时候先写思路再用注释把关键步骤标出来最后才写具体代码。这样即使代码有bug阅卷人也能看到你的思路是对的会酌情给分。还有一道让我印象深刻的概率题后来也在牛客网上看到别人回忆过一个袋子里有5个红球和3个蓝球每次随机取出一个球取出后不放回问第一次取出红球的概率是多少这道题很简单是5/8。但它真正想问的是第二问如果已知前两次取出的都是红球第三次取出红球的概率是多少答案是3/6即1/2。这道题考的是条件概率不是独立的重复试验。放在编程题的最后一小问本质上是在测你有没有基本的概率直觉因为后面很多算法场景比如随机化算法、采样都需要这种直觉。5. 从这套笔试题反推小米当年的选人逻辑和人才观5.1 为什么实习生笔试不考框架、不考项目反而考这些陈旧的东西2015年的时候互联网公司招聘实习生普遍不要求你熟练掌握框架。原因很现实实习生招进来是要培养的公司默认你的项目经验基本为零所以笔试的重点就从你会什么转向你值不值得培养。而值不值得培养在技术上怎么判断最好的标尺就是计算机基础数据结构、算法、操作系统、网络、编程语言。Java和Android是能直接拿来干活的技能所以会重点考。但为什么还要考操作系统和网络因为你在后续的工作中一定会遇到性能优化、内存管理、网络请求并发这些问题。如果你连进程和线程的区别都说不清楚iOS和Android的开发工作会寸步难行。小米2015年的产品线已经很庞大了手机ROM、云服务、路由器、电视每个部门都在招人他们需要的是基础扎实、能快速上手业务的新人而不是什么都只会一点点、遇到问题全靠百度的人。还有一个容易被忽视的点2015年移动互联网竞争进入白热化阶段各大厂都在抢人。笔试题目在一定程度上充当了公司品牌的功能。一套难的笔试题会让候选人觉得这家公司技术有深度值得争取。而一套全是基础题的卷子反而会让候选人觉得公司没水平。所以你会发现2015年大厂的笔试题普遍偏难偏怪这是一种双向筛选不仅要选出会的人还要让落选的人觉得这家公司果然牛。5.2 从笔试到面试一道题就是你以后工作方式的一面镜子笔试通过之后还有两到三轮面试。小米的面试风格在当时是比较务实的不太喜欢聊虚的。面试官会拿着你的笔试答卷让你现场重新讲一遍你的解题思路尤其是那些你答错了的题目。这个时候你的临场反应和复盘能力比答案本身更重要。我记得当年面试的时候面试官问我HashMap的底层数组大小为什么是2的幂次方这道题在笔试环节没有直接出现但它是以笔试题为引子延伸出来的。答案是为了在下标计算时用位运算hash (length-1)替代取模运算hash % length提高计算效率。如果你在笔试里把HashMap的原理背得滚瓜烂熟但这道延伸题答不上来面试官大概率会觉得你只是应试型背题选手实际理解不够深。还有一个细节小米的HR面会问你对小米产品的看法。2015年的时候很多人会提到性价比、米粉文化、生态链、智能家居。但后来我听说面试官真正想听的其实是你对一个产品从需求到落地流程的理解。你说我喜欢小米手环没问题但如果你能顺带分析一下手环的电池管理为什么用低功耗蓝牙而不是普通蓝牙那就会让人眼前一亮。这种跨领域思考的能力恰恰是笔试题目筛选不出来的。5.3 这几年笔试出题逻辑的变化对2015年题目的再审视如果你拿2015年的小米笔试真题和2025年的笔试题目对比会发现一个很有意思的现象基础题依然是绝对主力但出题方式发生了剧烈变化。现在的笔试更倾向于场景化出题。比如不直接问你HashMap的原理是什么而是给你一个场景有一个需要高并发读写、且对数据一致性要求不高的缓存系统你会怎么设计这种题没有唯一答案需要你对多种技术方案有综合理解。而2015年的题更像是一道道独立的证明题每道题考察一个明确的知识点知识面广但深度不大。这背后反映的是行业对实习生定位的变化。2015年实习生是预科生公司愿意花时间培养现在是即战力招进来最好一周内就能上手干活。所以笔试的考察重点从你有没有基础变成了你解决问题和快速学习的能力怎么样。工具类题目比如RESTful API设计、Redis缓存策略、消息队列选型开始频繁出现在笔试试卷中这在十年前是不可想象的。但从准备策略的角度看2015年的这套题给我最大的启发反而是无论笔试怎么变基础永远在。算法、数据结构、操作系统、网络、编程语言这些构成一个程序员底层能力的东西永远不会过时。你可能会因为时机错过一个风口语言但只要基础在转型速度就能跟上行业变化。6. 笔试之后的复盘与进阶这套2015年的题今天还能怎么用6.1 把每道错题当成一个知识入口而不是终点当年考完笔试大多数人的第一反应是对答案、估分、等结果。但现在回过头看这套题最有价值的地方不是那个分数而是它暴露出来的知识盲区。我在准备小米笔试的时候把操作系统里的死锁部分重新啃了一遍把Android的Handler机制源码看了一遍这些积累后来在我正式工作的时候都派上了用场。所以我的建议是不管你现在准备的是哪家大厂的笔试考完一定要做两件事。第一把每道错题对应到具体的知识点建一个知识盲区清单。第二针对每个盲区找3到5道同类题进行专项练习。如果你只是对一遍答案就扔到一边那这套题就白做了把错题当成入口你才能真正把知识点吃透。笔试本质上是广度优先遍历它先扫一遍你知识面的宽度再用编程题考察你知识面的深度。应对它的最好办法不是押题而是把计算机基础课的核心知识点按章节梳理成知识树。树建好了遇到什么题你都能定位到自己熟悉的位置。6.2 手写代码的训练方法从背题到默写再到当堂默写2015年笔试让我最大的收获是意识到了手写代码和IDE写代码的差距。如果你也想练好手写代码我推荐一个很简单的方法拿到一道题先在注释里写出思路和边界条件再开始写代码。写完代码后不要马上看答案自己手工模拟几组测试数据把代码执行一遍检查有没有越界、死循环、空指针。如果你连手写Java代码都还不熟练可以先从一些固定的模板开始练比如链表的反转、快排的partition、二分查找的三种写法左闭右开、右闭、左开右闭。这些模板背熟了笔试的时候会节省大量思考时间。但要注意背模板不等于背代码你要理解每个模板的适用场景和边界条件否则换一个问法就懵了。还有一点我想特别提醒手写代码的时候务必注意语句的完整性。比如变量要先声明再使用、循环要有结束条件、递归要有终止条件。很多人在白纸上写代码时会不自觉地省略一些IDE可以自动补全的部分这些省略在阅卷人眼里就是错误。6.3 笔试只是起点进入实习后真正的考题才开始最后聊点笔试之外的东西。通过小米暑期实习笔试只是拿到了入场券真正的工作考验是从入职第一天开始的。2015年小米的实习氛围称得上高强度你需要在短时间内熟悉代码库、理解业务逻辑、学会和产品经理沟通需求。笔试里那些知识点在工作里会以各种形式重新出现。比如你在笔试里答的Handler内存泄漏问题在工作中会变成一个真实的bug单某页面退出后延时任务还在执行导致内存不断上涨。你在笔试里答的HashMap线程安全问题在工作中会变成一次实际的应用崩溃多线程并发写入HashMap导致CPU飙升100%。笔试是模拟工作才是实战但恰恰是那些模拟题决定了你能不能拿到实战的门票。如果你现在正在准备实习笔试我有三句话想送给你第一基础题是基石永远不要觉得八股文没用第二手写代码要当成一种习惯去练不要只依赖IDE第三笔试不是终点而是你发现自己知识缺口的第一面镜子。2015年那套题已经过去了很多年但它教会我的东西到今天依然在用。最后分享一个我自己的习惯遇到任何一套笔试题不管考得怎么样我都会把完整的题目和自己的解答整理成一份笔记过几个月再拿出来重做一遍。你会发现同一道题半年之后你的解法可能已经完全不同。这种对比比任何模拟测评都更能体现你的成长速度。
返回列表