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

资讯详情

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

2015小米暑期实习笔试题复盘:从C语言基础到工程素养

2015小米暑期实习笔试题复盘:从C语言基础到工程素养 刚拿到这个题目的时候我心里其实挺感慨的。2025年再看“2015小米暑期实习笔试题”这批卷子已经过去整整十年。这十年里智能手机行业几经洗牌小米也从当年的“互联网手机黑马”变成了今天覆盖智能家居、汽车、操作系统的科技集团。但回头看这份笔试题它其实特别能反映2015年前后移动互联网爆发期对研发实习生的真实要求基础扎实、思维敏捷、能在有限时间内解决具体问题。很多同学在准备大厂实习笔试时容易陷入一个误区——疯狂刷LeetCode、背八股却忽略了企业出题背后的筛选逻辑。2015年的小米暑期实习笔试题目难度不算变态但覆盖面很广从C语言指针、数组到操作系统、网络协议再到逻辑推理和开放问答几乎是把“一个合格研发实习生应该具备的底层素养”完完整整地考了一遍。这篇文章就围绕这份笔试题把当年的题型分布、核心考点、答题策略和踩坑经验一次讲透。无论你现在正在准备大厂实习还是单纯想检验一下自己的计算机基础这份复盘都能给你一些参考。1. 当年这份笔试题的整体画像我先把2015年小米暑期实习笔试的基本情况摆出来。那会儿小米的校招和实习招聘还远没有现在这么“标准化”线上笔试系统也就是个简单的网页答题平台没有摄像头监控没有双机位但这反而更考验一个人的自律和真实水平。整套题大概120分钟满分100分题型分布大致如下表题型题量分值占比考察方向选择题20题左右30~40%C语言、数据结构、操作系统、网络简答题3~4题25%概念解释、方案设计、场景分析编程题2~3题35~40%数组、指针、字符串处理、算法实现开放题1题5~10%产品思维、学习能力、价值观匹配如果你只看分值占比会以为编程题最重要但其实选择题和简答题才是刷人的主力。为什么因为选择题覆盖的知识点极广而且很多题目挖了非常细的坑——比如数组名和指针的区别、sizeof的求值时机、结构体对齐规则、进程和线程的底层差异这些“背答案”能过但“不懂原理”一定露馅。小米当年的出题风格其实已经带着强烈的“工程实用”倾向不考偏题怪题而是考你写代码时最常用的那些基础细节。再说说这套题的整体难度定调。和同年份的百度、阿里、腾讯实习生笔试相比小米的题至少从体感上要“亲民”一些。百度的题更偏算法攻坚阿里的题更偏系统设计而小米的题则更像一份“计算机基础综合卷”。这背后其实反映了2015年小米的招聘策略——那时候小米正处于高速扩张期手机出货量猛增MIUI生态快速完善大量非核心业务需要能快速上手干活的实习生所以笔试更看重基础扎实度和解决问题的思路而不是刻意选拔竞赛型选手。如果你现在去翻当年的面经会发现很多通过笔试的同学未必是ACM大神但普遍是“基础打得牢、代码写得规范”的人。2. 选择题里的高频考点与“坑王”盘点选择题是整份卷子最容易失分也最容易拉开差距的板块。我结合当年考后的回忆和后来复盘的经验把高频考点分成几类每一类都挑一个典型陷阱展开讲讲。2.1 数组与指针一道题能考出三种理解层次“数组和指针笔试题”这个热搜词到现在还是常青树可见这个考点是多少代人的噩梦。2015年小米的选择题里几乎一定会有一道类似这样的题char *p hello; char arr[] hello; printf(%lu %lu, sizeof(p), sizeof(arr));考的就是sizeof作用于指针和数组时的不同结果。在64位系统上指针大小固定是8字节32位系统是4字节而数组的sizeof返回整个数组占用的字节数arr是6字节包括结尾的\0。这是第一层理解。第二层理解是两者在“取值”和“传参”时的差异。数组名作为实参传给函数时会退化为指向首元素的指针所以在函数内用sizeof得不到数组长度。很多同学背了“数组名退化为指针”这句话但题目只要换个角度问“下面哪种写法能正确遍历二维数组”就会露馅。二维数组名退化为指针时类型是int (*)[N]而不是int *如果你拿int *去接编译器直接报警告甚至报错。第三层理解是“数组和指针到底能不能互换”。很多教材说“数组名就是指针”严格来说这是错的。数组名是一个地址常量不能自增自减不能重新赋值而指针变量可以。arr是非法的但p合法。当年有一道真题就专门考了*(a1)和*a1的区别前者是“数组第二个元素”后者是“首元素的值加1”这两个结果完全不同。这个细节特别能区分“背过知识点”和“真正写过程序”。2.2 结构体对齐一道题暴露你有没有做过嵌入式2015年小米的笔试里结构体字节对齐的题几乎是必考内容。我记得当时有同学考完抱怨我学的是Java拿C/C的题考我结构体对齐意义在哪其实意义很大——小米有大量硬件相关的业务路由器、智能家居设备、手机底层驱动这些全是C语言的主场。结构体对齐直接关系到内存布局、通信协议解析和底层驱动开发做嵌入式方向的同学必须烂熟于心。给你一道典型的题感受一下struct A { char a; int b; char c; }; printf(%lu, sizeof(struct A));在常见32位/64位编译器默认对齐规则下结果是12而不是6。原因是int类型需要4字节对齐所以存储布局是a占1字节填充3个字节b占4字节c占1字节最后整体对齐到4字节边界再填充3个字节总计12字节。如果把结构体成员的顺序改为int b; char a; char c;大小就变成8字节省了4字节。这类题的重点不是让你记住每个平台的对齐值而是要你理解“为什么对齐”CPU访问对齐数据的效率远高于非对齐数据有些架构甚至直接不支持非对齐访问。像小米做IoT设备如果协议解析时没考虑对齐在PC上跑得好好的放到ARM芯片上就崩溃这种问题排查起来极为崩溃。所以这道题表面考内存布局实际是在考察你有没有处理真实硬件问题的意识。2.3 操作系统与并发进程和线程不能只背定义选择题里操作系统的占比也比较稳主要是进程与线程的区别、死锁的四个必要条件、虚拟内存和分页、用户态与内核态切换。最经典的一道题是进程和线程的根本区别是什么 A. 进程有独立的地址空间线程共享地址空间 B. 进程切换开销小于线程 C. 线程可以并发执行进程不能 D. 进程有优先级线程没有答案选A但很多同学会在B和C上犹豫。B看起来有道理但因果倒了——线程切换开销小正是因为线程共享地址空间不需要切换页表等上下文。C是错的进程同样能并发执行。这道题考的不是记忆而是你能否建立“机制决定代价”的因果关系。如果你只会背“进程是资源分配单位线程是调度单位”碰到这种变体题还是容易错。还有一道高频题是死锁的四个必要条件互斥、持有并等待、不可剥夺、循环等待。小米当年喜欢把条件变成实际场景来考比如问“下列哪个操作可以破坏循环等待条件”答案是资源有序分配法。这道题本身不难但它后面往往跟着一个简答题“设计一个方案避免多线程抢锁造成的死锁”这就需要你真正理解锁的粒度、锁的顺序、超时机制这些工程经验而不只是背四个名词。2.4 网络协议不考细枝末节考你日常排障够不够用网络部分的题量不大但每年都会出。2015年左右移动互联网正是风口小米的MIUI、米聊、云服务都重度依赖网络通信所以笔试里出现TCP三次握手、HTTP状态码、DNS解析过程都太正常了。我记得有一道选择题考的非常务实用户在浏览器输入网址后下列哪个事件最不可能立即发生 A. DNS查询 B. 解析HTML C. 建立TCP连接 D. 发送HTTP请求答案是B因为解析HTML要等服务器返回响应报文之后才发生。这题看似简单但不少人会选A他们的理由是“浏览器有缓存”。出题人故意在这里设置了一个理解偏差DNS查询可能被本地缓存命中不是每次都发生但“最不可能立即发生”的是拿到响应之后才能做的解析动作。这类题目就是在考察你对网络请求生命周期的整体把握而不是死记硬背某个状态码的含义。另一道常考的题是TCP和UDP的区别。小米当年的考法不是让你列概念而是给一个具体业务场景视频通话应该用TCP还是UDP为什么标准回答是视频通话对实时性要求高能容忍少量丢包不能容忍重传带来的延迟所以一般基于UDP而文件传输必须保证完整性所以用TCP。这个答案并不难但你要能说清楚“TCP的重传机制为什么会导致延迟”这就涉及到拥塞控制、超时重传这些机制了。能把“为什么”讲清楚的同学面试官在后续面试中会明显更愿意深聊。3. 算法与编程题不秀技巧看你基础功2015年小米暑期实习笔试的编程题放到今天看依然很有代表性。它不考复杂的动态规划也不考冷门的图论而是更偏向链表操作、字符串处理、数组变换这类“基本功中的基本功”。这背后传递的信号很明确实习生入职后大量的活是写业务代码、处理数据、修bug而不是设计高深算法。3.1 数组去重与排序多写几个测试用例你就赢了有一道我印象很深的代码题给定一个无序整型数组要求原地去重并输出排序后的结果。题目要求不能使用额外数组只能使用常数额外空间。很多人第一反应是“排序后再相邻去重”思路没错但实现时容易忽略边界条件。比如数组长度为0或1的情况比如数组里全是相同元素的情况再比如去重后数组的长度如何更新。这道题除了算法本身更看重你能不能写出健壮的代码。我当时提交的解法思路是快速排序加双指针去重快速排序平均复杂度O(n log n)原地去重部分O(n)整体满足要求。代码大概长这样#include stdio.h void quickSort(int* nums, int left, int right) { if (left right) return; int pivot nums[left]; int i left, j right; while (i j) { while (i j nums[j] pivot) j--; nums[i] nums[j]; while (i j nums[i] pivot) i; nums[j] nums[i]; } nums[i] pivot; quickSort(nums, left, i - 1); quickSort(nums, i 1, right); } int removeDuplicates(int* nums, int numsSize) { if (numsSize 0) return 0; int slow 1; for (int fast 1; fast numsSize; fast) { if (nums[fast] ! nums[fast - 1]) { nums[slow] nums[fast]; } } return slow; }这段代码里removeDuplicates部分用的是双指针思路慢指针指向“下一个不重复元素应该存放的位置”快指针负责遍历。最关键的判断条件是nums[fast] ! nums[fast - 1]也就是只有碰到第一个和新元素不同的值时才写入。这个逻辑写起来简单但错写一个边界就会数组越界或保留重复值。我当时写完后自己补了三个测试用例空数组、全重复数组、负数和正数混合的数组确认都没问题才提交。多写测试用例这个习惯帮我挡住了至少两处隐藏bug。3.2 链表反转能写出循环版更要能讲清递归版链表的题在笔试中也属于高频题因为链表操作特别能考察指针相关的细节。2015年小米的卷子里有一道“反转单链表”要求写出代码并分析时间复杂度。迭代版本我用的是经典的“三指针”法pre、cur、next三个指针轮流推进每步把cur的next指回pre然后整体右移。递归版本更简洁但思路需要绕一下——先反转当前节点之后的链表再把当前节点放到反转后链表的末尾。递归版有个陷阱就是忘记把当前节点的next置为NULL导致链表成环。很多同学笔试时写了递归版自以为对了其实内存里已经死循环了。这类细节纸质笔试很难暴露但在面试现场手写代码时会被面试官一眼看穿。链表题为什么这么常考因为它的每一步操作都不能出错而且非常依赖你对“引用”“指针”“对象指向”这些底层概念的理解。Java、Python方向的同学即使不直接用指针也必须理解对象引用的本质是“指向一块内存的地址”否则反转链表这种题写起来会很别扭。3.3 字符串与进制转换小题目里的大坑还有一道跟字符串有关的编程题实现一个函数把十进制的数字字符串转换成整数比如输入-123输出-123输入255输出255。看起来简单但出题人设置的隐藏考察点很多正负号处理、空字符串、非法字符、整数溢出。当年很多同学就是折在这道“简单题”上。正常的解法是先判断符号位再逐位累加。累加公式是result result * 10 digit但如果没有判断溢出输入2147483648就会越界变成负数。C语言里可以用if (result (INT_MAX - digit) / 10)来提前检测溢出。Python里虽然整数没有固定位数但面试官会问你“如果语言没有大整数支持怎么办”考察的还是底层敏感性。另外还要考虑字符串中间出现空格或特殊字符的情况。题目如果没说输入一定合法你就必须自己定义行为是返回0还是报错合理的实现应该至少明确区分“非法输入”和“合法输入0”。这类题之所以常考是因为真实开发中从配置文件、接口报文、用户输入中解析字符串的场景数不胜数。如果连“字符串转整数”都写不好后面做业务代码肯定埋雷。4. 简答题和开放题小米当年真正想听的是什么编程题决定你能不能进面试但简答题和开放题往往决定面试官对你“有没有兴趣”。小米2015年的卷子里简答题一般有3道左右开放题有1道。这几个题的答案没有标准但特别能看出一个人的思维方式。4.1 方案设计题给一个iOS/Android消息推送的简化方案这类题出题人真正想考察的是“你有没有系统思维”。消息推送听起来很简单——App连上服务器服务器把消息转发给App。但你要是只回答这个层面得分会非常低。你需要拆解出一个简化但完整的链路客户端和服务器之间维持长连接比如TCP长连接、服务器需要知道每个设备在哪里也就是设备标识和IP地址的映射关系、消息发送失败后怎么办离线消息要不要存储、要不要重推、多端登录怎么处理手机上已读平板要不要同步已读状态。我当时的回答思路是分模块连接管理模块负责心跳保活、消息管理模块负责下发和确认、存储模块负责离线消息。然后针对“消息可靠到达”这个核心目标设计了ACK确认和超时重发的机制。这道题不需要你做代码实现但每一个环节都要说到“为什么”为什么要心跳因为NAT超时会断开连接为什么要有ACK因为TCP只能保证包到达不能保证业务层一定处理成功。把这些逻辑串起来面试官就知道你是有通信项目经验的或者至少是真的思考过这类问题。4.2 学习能力题反映你平时怎么获取知识有一类开放题是这种画风“你最近在研究什么新技术说说你如何学习一门新语言或新框架”这类题没有标准答案但特别容易暴露一个人的真实学习习惯。2015年那会儿深度学习概念刚开始火TensorFlow还没发布Android开发还是Java的天下Kotlin都还没成为Android官方语言。如果你在那年能说出“我在看Flutter”或者“我在研究Swift”其实已经是很超前的信号了。但更多同学回答的是“我在刷题”“我在看网课”这种回答在面试官眼里约等于没回答。更好的回答结构是最近遇到什么问题 - 通过什么渠道了解到某个方案 - 踩了什么坑 - 最后如何解决的。这种“问题驱动”的学习路径远比“我学了很多技术名词”有说服力。4.3 价值观匹配题小米的“和用户交朋友”还有一道题大意是“你如何看待用户反馈和产品迭代之间的关系”。小米的价值观一直是“和用户交朋友”所以这样的题本质是在筛选认同这种理念的人。但回答时不需要刻意喊口号更忌空洞地说“用户是上帝”。最好的回答是举一个你真实经历过的例子比如你在某个开源项目里提过issue、给某个App反馈过bug、或者自己写小程序时收到用户提意见后的处理流程。我当年回答时讲了一个自己做课设网站的经历室友反馈说页面在手机上打开排版错乱我第一反应是“他手机浏览器的问题”后来顺手用浏览器开发者工具模拟了手机屏幕才发现确实是布局没有适配。这个经历让我意识到用户反馈即使描述得不专业背后也一定有真实的使用场景开发者的工作是听懂场景而不是急着反驳。这个回答得到了面试官的点头说明“真实”比“标准答案”更重要。5. 实操复盘笔试中的时间分配与答题顺序很多同学笔试挂掉不是因为不会而是因为时间没分配好或者答题顺序有问题。我在这里把当年总结的实操策略分享出来这套策略到现在依然适用。5.1 拿到卷子先做的三件事第一件事用2分钟把整卷从头到尾扫一遍做到心里有数。重点看编程题有几道、难度如何、简答题问的是什么。我当年拿到卷子后先定位了三道编程题发现两道是数组和基础算法题、一道是链表题心里就有底了这卷子不会太离谱。第二件事先做选择题但不要恋战。选择题的单题分值不高卡住超过2分钟就先蒙一个并在草稿纸上标记后面有时间再回头验算。很多选择题的坑藏在细节里你越想越容易钻牛角尖不如先放一放等做完其他题再回来看往往一眼就能看出问题。第三件事编程题先写思路再写代码。即使是在线笔试没有人工阅卷很多系统也有自动评分或代码检查你写注释和思路不会加分但边写思路边理清逻辑能大幅降低bug率。我习惯先写一版伪代码比如“先排序 - 再用双指针去重 - 返回新长度”然后再把伪代码逐步翻译成C语言。这个习惯帮我省掉了大量调试时间。5.2 时间分配建议45-45-15原则我的实际经验是把120分钟按“45分钟选择题45分钟编程15分钟检查15分钟机动”来切分。选择题部分尽量一遍过犹豫不决的题不超过2分钟。编程题先挑最熟悉、最有把握的做把保底分拿到手再攻难题。剩下15分钟是机动时间用来补之前跳过的选择题和检查编程题边界条件。千万不要在选择题上花70分钟然后编程题只剩20分钟仓促写完一堆半成品这是最亏的。因为编程题的分值占比高而且只要写对思路并且没有致命bug即使不是最优解也能拿到大部分分数。反过来选择题错5道但编程题全对总分往往依然不错。5.3 一个被忽略的隐形加分项写代码的“工程素养”2015年的在线笔试其实还是人工阅卷为主代码会被人看到。这个时候变量命名的规范程度、有没有处理边界条件、有没有写注释、有没有明显的资源泄漏都会影响阅卷人的主观评分。我当时比较得意的一个细节是在链表反转那道题的代码里我给函数加了一行注释“如果head为空或只有一个节点直接返回原链表。”这行注释表面上在描述一种边界情况实际上向阅卷人传递了一个信号我写代码考虑过空指针我见过真实项目里因为空指针导致崩溃的问题。这种意识在笔试评分时非常拉好感。反观有些人写的代码循环里指针一个劲地往前挪也不判断是否已经走到链表尾部这种代码即使逻辑结果是对的观感也很差。6. 笔试通过后的衔接从试卷到面试怎么乘胜追击笔试只是第一道关卡通过之后才是正式面试。2015年小米的暑期实习面试一般是两到三轮技术面加一轮HR面面试的问题与笔试高度相关但会问得更深。我在这里说几个“笔试后到面试前”的黄金准备动作。6.1 复盘试卷里的每道错题笔试结束后的当天晚上趁记忆还热乎把能回忆起来的题目都写下来逐个查资料、验证答案。这一招非常重要因为面试官经常会拿着你的笔试卷子来提问比如指着你错的那道结构体对齐题问“你现在知道为什么是12了吗”或者指着你蒙对的网络题问“你当时选B的理由是什么”。如果答不上来印象分会大打折扣反过来如果你能清晰说出“我笔试时哪里想错了后来怎么纠正的”面试官反而会认为你有学习能力。我当年就在复盘时发现一道选择题做错了——进程间通信方式中哪种方式最快我选了“管道”实际上“共享内存”才是最快的。复盘后我专门把进程间通信的几种方式做了对比整理管道适合父子进程、消息队列适合解耦、共享内存适合大数据量交互、Socket适合跨机器通信还补充了“为什么共享内存最快”的原因——因为它不需要内核态和用户态之间的数据拷贝。这个知识点在面试时正好被问到了我能脱口而出面试官明显很满意。6.2 把笔试中没写完的代码补完整如果你笔试时有一道编程题只写了一半那么面试前一定要亲手把它补完而不是只在脑子里想“我会做”。动手写一遍和看别人的题解是完全不同的体验。补代码的时候刻意用自己最不熟悉的语言再写一遍比如笔试时用的C面试前用Java或Python再写一遍这样遇到“用你熟悉的语言实现一下”的面试题时才不会慌。手动补代码还有一个好处是能发现新的边界条件。比如字符串转整数那题补写时我发现了“只传了号”这种极端输入C语言的atoi函数会返回0但如果自己实现就得明确返回0还是报错。这类细节都是面试官愿意听到的。6.3 提前准备“为什么选择小米”的回答笔试过了以后面试必问“你为什么选择小米”这个问题一方面看你的求职动机另一方面看你对公司的了解程度。2015年这个时间点小米刚发布了小米Note正在从“为发烧而生”往“品质生活”转型生态链产品开始多点开花这些都可以成为回答的素材。但更重要的还是结合你投递的岗位来说。如果你投的是Android开发你可以说MIUI在定制系统领域的探索吸引了你如果你投的是后台开发你可以提到米聊、云服务等对高并发的挑战如果你是冲着智能硬件来的那就应该聊一下你对小米路由器、智能家居这套体系的看法。总之回答里最好体现你研究过小米的业务而不是万金油地说“我很喜欢小米的产品”。6.4 面试中的代码追问多想想“如果数据量变大呢”最后再提醒一点笔试后的技术面试必有一部分是现场写代码或代码追问。面试官最喜欢做的一件事就是把你笔试的简单题升级成一个“大数据量版本”。比如你笔试写了数组去重排序面试官会追问如果数组里有100亿个整数内存装不下怎么办这种时候你就要想到外部排序、哈希分片、Bitmap位图法、Bloom Filter这些大数据处理的常见套路。不需要你说得非常完整但至少能说出“先分片再对每个分片处理最后归并”这样的思路。这个追问考察的不是你背诵了多少算法而是你有没有在夜深人静的时候想过“这个方案在生产环境中到底扛不扛得住”。7. 我踩过的坑和希望你知道的事写到这里我脑子里其实浮现了不少2015年那个夏天前后的画面一边刷着笔试题库一边翻着小米的发布会在宿舍的破台式机上敲代码敲到凌晨。这么多年过去当年那些具体的题我已经忘得差不多但有几条经验是我后来带实习生、做校招面试官时总忍不住反复提起的索性在这里一并分享给你。第一大坑只刷题不总结等于白刷。很多人准备笔试时一天能刷几十道题但每道题都是“看答案-觉得懂了-下一题”。这种刷法的最大问题是你在做题时没有建立起“考点分类”的框架。你做一道结构体对齐应该顺便总结出“所有C语言内存布局题”的通用解法你做一道数组去重应该顺便总结出“所有双指针问题”的切入角度。真正高效的准备不是题量的堆积而是每做一道题都能沉淀出一个可以迁移到同类型问题的方法论。第二个坑只在脑子里想思路不亲手写代码。尤其是笔试环境往往是在线编辑器没有代码补全、没有编译调试提示你平时在IDE里能轻易发现的语法错误到了笔试环境里全靠肉眼排查。不亲手写够一定量的代码到了考场上会非常生疏。我当年备考时每天晚上睡前固定用一个小本子手写两三道代码题不运行只靠人工检查。这个习惯虽然老土但极大提升了我在白板/代码框里写代码的准确度。第三个坑小看开放题。不少人觉得简答题和开放题随便写两句就行反正阅卷人不会仔细看。实际上对于编程题大家都做得差不多的卷子简答题反而是区分度最高的地方。因为选择题会有人蒙对编程题可能因为边界问题被扣分但简答题写得好不好、有没有结构、有没有思考深度阅卷人一眼就能分辨。认真对待每一道题本身就是一种态度。现在回头看2015年的小米暑期实习笔试题目本身可能已经过时——那会儿Android还停留在大版本迭代的早期Java还没被Kotlin挑战容器、微服务也远没有像今天这样普及。但这份卷子背后的考察逻辑到今天依然适用基础扎实、逻辑清晰、在意细节、有工程意识。你在准备任何一场笔试时如果能主动往这个方向靠拢就不只是在应付考试而是在培养一种会伴随整个职业生涯的工作习惯。
返回列表