☰
滴滴2016研发笔试题解析:数组指针、链表与TCP核心考点
2026/10/28 3:22:51 网站建设 项目流程

滴滴出行2016研发工程师笔试题,这份试卷在技术社区的题库里躺了很多年,但今天翻出来看,含金量一点没缩水。当年参加这场笔试的人,现在大多已经在各家互联网公司成了技术骨干,而试卷上反复出现的数组、指针、链表、进程线程、TCP协议这些考点,依然是如今国内互联网公司研发岗笔试的标配内容。我这篇博文就围绕这套题的考点展开,把每类题目的考察意图、解题思路、容易踩的坑逐一拆开,给正在准备秋招的朋友一份可以直接参考的备考清单,也帮已经工作几年的老工程师回头补补基本功。不管你是主攻Java还是C/C++,不管目标是滴滴还是其他大厂,这套题背后的知识体系都值得认真过一遍。

1. 试卷整体结构与考点分布

1.1 笔试题型与考察范围

先看试卷结构。2016年前后的互联网公司研发岗笔试,主流形态是“选择题 + 编程题”,少数公司会加填空题和简答题。滴滴这份笔试题(一)整体延续了这个套路,大致可以分成两部分:

  • 客观选择题,主要覆盖C/C++语言基础、数据结构、操作系统、计算机网络。
  • 编程大题,以算法设计为主,常见的有数组处理、链表操作、字符串处理、简单动态规划或贪心。

从考点占比来看,互联网公司研发笔试的分布很固定,大致是:语言基础约30%,数据结构与算法约40%,操作系统和计算机网络约20%,其他杂项(Linux命令、数据库、设计模式、智力题)约10%。滴滴这套题也基本符合这个规律。之所以形成这种结构,是因为笔试的本质是海选工具,在有限的时间内用标准化题目快速筛掉基础不扎实的候选人。选择题客观、易判、覆盖面广,编程题则能直接反映写代码的硬功夫,两者结合是成本最低的初筛方式。

如果你对比过国企或传统软件公司的笔试题,会发现它们的口味明显不同——更偏向Java基础语法、数据库SQL、Linux操作命令,算法题占比很低。而滴滴这类互联网公司更看重计算机底层功底和算法思维,因为线上业务的高并发、高可用场景,最终都要落到数据结构、操作系统、网络这些基础课上。

1.2 为什么研发岗笔试偏爱这些考点

很多同学会问:工作里每天写业务代码,谁还手写反转链表、手写快排?这个问题我当年也困惑过。后来做了几年面试官,慢慢理解了笔试考点的设计逻辑。

以数组和指针题为例,它考察的不是“你会不会用数组”,而是“你是否真正理解内存模型”。C/C++里数组名和指针的关系,直接反映一个人对栈区、堆区、地址偏移这些概念的理解程度。写业务代码时你可能永远不需要手动管理内存,但如果连sizeof(arr)和sizeof(p)的区别都说不清,面试官很难相信你能排查内存泄漏、分析线上崩溃问题。

算法题同理。手写一个层序遍历或反转链表,看起来和实际工作没直接关系,但它考察的是逻辑思维是否严密、代码风格是否干净、边界条件是否敏感。这些素质恰恰是研发工程师最重要的底层能力。系统设计、性能优化、故障排查,归根结底都在用这套思维方式。所以与其吐槽笔试题脱离实际,不如把每一道题背后的知识点吃透,它们才是支撑你走得更远的地基。

2. 高频题型逐题拆解:从读懂题意到写出满分答案

2.1 数组与指针:C/C++考生必过的第一关

数组和指针是笔试选择题里的绝对主力,几乎每套试卷都会出现2到3道。因为C/C++笔试是当时大陆公司研发岗的主流选择,滴滴这套题自然也不例外。这类题考察的点很集中,核心就是对内存模型的理解。

先看一道出镜率极高的经典题。以下代码在64位平台上输出什么?

#include <stdio.h> #include <string.h> int main() { char str[] = "hello"; char *p = str; printf("%lu %lu\n", sizeof(str), sizeof(p)); printf("%lu %lu\n", strlen(str), strlen(p)); return 0; }

正确答案是6 8和5 5。str是数组,sizeof(str)等于整个数组占用的内存,字符串"hello"有5个字符加上结尾的\0,所以是6字节。p是指针,64位平台下指针占8字节,和它指向的内容无关。而strlen关心的是字符串内容,它数到\0就停,所以两个都是5。

这个题的坑在于:如果你把str作为参数传进函数,情况就不一样了。看下面这版:

void func(char arr[]) { printf("%lu\n", sizeof(arr)); }

输出是8,不是6。因为数组作为函数参数时会退化成指针,char arr[]本质上就是char *arr,sizeof计算的永远是指针的大小。理解这一点,就理解了C语言里“数组参数退化”的规则。

再来看另一个高频变体,二维数组的指针偏移:

int a[3][4]; int *p = a[0];

问a + 1、&a + 1、p + 1分别指向哪里。a作为数组名,在表达式中代表指向首元素的指针,首元素是一个长度为4的int数组,所以a + 1跨过4个int。&a取的是整个二维数组的地址,&a + 1直接跨过整个a数组,也就是跳过了12个int。p是int*,p + 1只跨过1个int。这道题把“数组名、取地址、指针算术”三个核心概念一次考透,是经典中的经典。

给准备笔试的同学一个实操建议:遇到sizeof相关题目,先判断对象是数组类型还是指针类型;遇到指针加减,先问自己一句“当前指针指向的基本单位是什么”。这两个习惯能帮你避开80%的陷阱。

2.2 算法设计:现场手写代码的得分点

算法编程题是笔试的重头戏,也是拉分项。选择题大家靠积累,编程题则直接暴露你的代码硬实力。滴滴这套题的编程题风格和同时期其他大厂类似,不会出太偏难怪的题,基本都是经典算法的高频变体:Two Sum、反转链表、链表判环、数组去重、二分查找边界、最长公共子序列等。

以“找出数组中出现次数超过一半的数字”为例,这题在2016年前后的笔试出现率极高。最直观的解法是排序后取中间值,时间复杂度O(n log n)。但如果你知道摩尔投票法,就能写出O(n)时间、O(1)空间的满分答案:

public int majorityElement(int[] nums) { int candidate = nums[0]; int count = 1; for (int i = 1; i < nums.length; i++) { if (count == 0) { candidate = nums[i]; count = 1; } else if (nums[i] == candidate) { count++; } else { count--; } } return candidate; }

摩尔投票法的核心思想是“不同元素互相抵消”。出现次数超过一半的元素,即使和其他所有元素一一抵消,最后也一定会剩下来。因此用一个计数器,遇到相同的候选就加一,遇到不同的就减一,计数归零时更换候选。这个过程不容易一眼看懂,但代码实现非常简洁。

笔试判分时,面试官看重的是三点:思路是否清晰、边界是否处理干净、复杂度是否达标。我见过很多同学代码能跑通,但没写注释、变量名全是a b c,或者只写出O(n log n)版本而不知道有O(n)解法。这些都是扣分点。正确姿势是:先在草稿纸上写清楚思路和复杂度,再动手敲代码,写完后用一两个特殊用例(空数组、全相同元素、长度1)自测一遍。

这类算法题背后其实有一个共同套路:很多题都可以归为“如何用哈希表/双指针/单调栈/动态规划来优化暴力解法”。刷题时不要满足于AC,多想想为什么这个解法能成立,有没有更优方案,这样在笔试现场遇到新题才不会慌。

2.3 系统与网络基础:研发工程师的底线知识

操作系统和计算机网络的选择题,占分不如算法高,但往往是你和别人拉开差距的地方。原因很简单:这两块知识靠考前突击很难补,必须是真的理解过、实践过才能答对。

先看操作系统的高频考点。进程与线程的区别是必考题,核心考点在于:进程是资源分配的基本单位,线程是CPU调度的基本单位;同一进程下的线程共享内存空间,而进程之间相互独立;线程切换的开销比进程小,因为不需要切换地址空间。配套的扩展考点还有:多线程共享哪些资源、独占哪些资源、线程安全怎么保证、死锁的四个必要条件以及如何破坏。

死锁题尤其喜欢考“如何破坏循环等待条件”,标准答案是资源有序分配法:给所有资源编号,线程只能按编号递增的顺序申请资源。这类题目的意义在于,分布式系统和数据库并发控制中都大量应用了类似的资源管理思路。

计算机网络同样是选择题大户,最经典的是TCP三次握手和四次挥手。不要只背“三次握手、四次挥手”这六个字,笔试喜欢挖细节:为什么握手是三次不是两次,为什么挥手要四次而不是三次,TIME_WAIT状态为什么需要等待,等等。

我建议每个准备笔试的人,都亲手画一遍“输入URL到页面展示”的完整流程:DNS解析、TCP连接建立、HTTP请求发送、服务器处理、响应返回、浏览器渲染。这个链路题几乎是大厂面试的标配,画明白这一条链路,DNS、TCP、HTTP、浏览器渲染的知识点就串起来了,比零散背题效率高得多。

再来一道网络选择题实例:HTTP与HTTPS的区别,标准答法是:HTTP明文传输,HTTPS在HTTP和TCP之间多了TLS/SSL加密层;HTTPS默认端口443,HTTP默认端口80;HTTPS通过证书验证服务器身份,能防止中间人攻击。深层考点则是TLS握手过程中如何交换密钥、如何保证完整性,这些内容在系统设计面试里还会反复出现。

3. 答题策略与时间分配

3.1 两套时间分配方案

笔试现场最大的敌人不是题目太难,而是时间不够。2016年滴滴这套题,整体难度属于中等偏上,选择题大约25道,编程题3到4道,总时长120分钟。如果没想好时间策略,很容易出现前面选择题纠结太久、后面编程题草草了事的局面。

我的建议是先做选择题,后做编程题,但选择题要严格控制时间。这是因为选择题只需要勾选答案,不需要构造思路,做起来性价比高;编程题哪怕想得慢,通常也能在白纸上写点思路拿过程分。具体到120分钟,可以这样分配:

环节建议用时策略要点
第一轮选择题25分钟会做的直接选,不会的立刻标记跳过
第二轮回头补选择题10分钟优先处理标记题,再纠结难题
编程题三道70分钟每题约20分钟,最后留10分钟检查
机动时间15分钟压轴题、复查答案、补注释

如果是90分钟的笔试,把选择题压缩到20分钟,编程题压缩到60分钟,机动时间10分钟。核心思路不变:选择题一旦卡住超过2分钟,永远先跳过,回头有空再想。很多同学一遇到选择题就犯强迫症,非要选出答案才往下走,结果一道题磨了5分钟,后面编程题全乱了。我把这叫作“单题局部最优导致全局劣优”,是做笔试的大忌。

3.2 答题顺序与取舍策略

做题顺序也有讲究。我个人的习惯是三遍式:第一遍扫一遍全卷,把会做的题全部解决掉,尤其是那些一眼就能看出答案的送分题,先把它们拿稳;第二遍回头啃标记过但有点思路的题;第三遍才是难题和压轴题。

编程题的顺序建议按熟练度来,不按题目顺序。如果你对链表题最熟,就先写链表那道;如果你擅长动态规划,就先写动态规划那道。把最有把握的先解决,不仅保证得分,还能建立信心,避免因为第一道编程题卡壳导致后面全崩。

编程题的取舍也有技巧。如果一道题思考了10分钟还没有完整思路,不要死磕,先写一个暴力解,保证能过部分用例,再把复杂解的核心优化思路写在注释里。笔试判卷时,暴力解有机会拿30%到50%的分,空着则一定是0分。写下过程和思路非常关键——很多公司有面试官人工复核笔试答卷,你的解题思路比答案本身更能反映能力,即使最终代码不能完全跑通,清晰的思路也能给你争取一面机会。

4. 从笔试到面试:这道题背后的准备方向

4.1 按专题训练,把题库过成体系

笔试不是终点,面试才是。笔试题目里暴露出的薄弱点,如果不及时补上,面试时会被追问得更狠。我见过太多人笔试算法题写出来了,面试官追问“为什么这里用哈希表不用数组”“这个复杂度还能不能再优化”,直接卡壳。所以备考要按专题系统过,不要零散刷题。

按数据结构分类,建议按这个顺序准备:数组和字符串 → 链表 → 栈和队列 → 二叉树 → 哈希表 → 图 → 动态规划 → 贪心。每个专题至少练习15到20题,并总结出这个专题的常见套路。比如链表题的核心套路就是“哑节点 + 双指针”,二叉树题的核心套路是“递归 + 迭代栈”,动态规划题的核心套路是“定义状态 → 找转移方程 → 确定边界条件”。

再细化一点,链表题有一类高频变体,就是“判断链表是否有环,并找到环的入口”。快慢指针找环是经典解法,但找到入口需要再推一步:相遇后,慢指针继续走、快指针重置为头节点并改为一步走,两者再相遇的位置就是入口。这个推导过程经常被面试官要求现场讲清楚,如果你只背答案不会推,一追问就露馅。做题之余,把每一步推导搞懂,才是真的在准备面试。

Java方向的同学,还可以多留意JVM内存模型、并发编程、集合源码这些笔试选择题里的“编外考点”。2016年后Java岗位逐渐增多,很多公司的笔试会加入Java专项选择题:HashMap的底层结构、ConcurrentHashMap如何保证线程安全、ArrayList和LinkedList的区别、synchronized和volatile的区别。这些既是笔试高频题,也是面试必问题,建议提前整理出自己的话术,不要只会背名词。

4.2 把项目经历串起来,让知识落地

笔试考的是知识,面试考的是应用。面试官看到你的简历写“参与过XX系统的性能优化”,大概率会追问:“底层是怎么做性能分析的?服务吞吐量为什么从1000提升到3000?JVM参数怎么调整的?Full GC为什么减少了?”这些问题,本质上都在考操作系统、网络、数据结构的基础原理。

所以准备校招时,不要只埋头刷题,要把自己的项目经历做一次“考点映射”。比如你做过一个Web服务,可以试着问自己:

  • 用户请求从进入到返回,经过哪些环节?每个环节可能有什么性能瓶颈?(对应网络、操作系统)
  • 如果用户量增大10倍,哪个组件最先成为瓶颈?数据库?应用服务器?带宽?(对应系统设计)
  • 服务日志量很大,用什么数据结构、什么算法统计出高频接口?(对应数据结构与算法)
  • 如何保证多线程并发请求下,数据的一致性?(对应并发编程)

这个过程能帮你把笔试学到的知识真正内化,面试时也更有底气。不要等到拿到面试通知再突击,笔试准备阶段就同步开始整理,效率最高。

5. 踩坑实录与备考建议

5.1 笔试现场最常见的三个翻车点

第一个翻车点是审题不仔细。题目要求O(n)时间复杂度,你写了个O(n log n)的排序解法,用例能过,但分数很低;要求原地修改数组,你又新开了一个数组;要求处理空输入,你直接对第一个元素取下标,跑起来就抛异常。我的习惯是,编程题动笔前,把题目里的限制条件用笔圈出来,写完后对照限制条件自查一遍。

第二个翻车点是边界条件处理不完整。二分查找的left <= right还是left < right,循环结束后的返回值是什么;链表反转后头节点是否指向null;递归的退出条件是否覆盖了长度为0的情况。边界条件通常只占代码量的10%,却决定了代码正确率的90%。建议准备一个边界条件检查清单:空输入、单元素输入、元素重复、溢出、指针为null,每道题写完都按清单过一遍。

第三个翻车点是代码风格太随意。我批改笔试时见过不少代码,变量名是a、b、c,没有缩进,没有注释,核心逻辑混在一起根本看不清。这类代码即使算法对了,也容易被扣印象分。建议平时刷题就养成规范习惯:函数名用动词开头、变量名见名知义、关键步骤写一行注释、复杂逻辑拆成小函数。这些习惯在面试手撕代码时也是加分项。

另外提醒一下,笔试环境往往和你平时开发环境差别很大,很多公司的在线笔试系统不提供本地编译器,需要直接在网页代码框里写代码。这意味着不能依赖IDE的自动补全和语法检查。平时练习时尽量用纯文本编辑器写代码,再放到IDE里验证编译,提前适应这种“裸写”的紧张感。

5.2 刷题方法论:少走弯路的三个习惯

最后聊一下有效的备考节奏。我不建议一上来就搞题海战术,更推荐“专题突破 + 思维导图 + 错题复盘”的组合。

第一个习惯是专题突破。设定每周只刷一个专题的题目,比如这一周专攻二叉树。好处是能快速建立同类题型的模式识别能力:看到中序遍历立刻想到递归或栈,看到层序遍历立刻想到队列。如果今天刷链表明天刷图,知识点是散的,遇到新题很难联想到解法。

第二个习惯是画思维导图或笔记。每做完一类题,把通用套路、边界陷阱、复杂度分析记下来。比如动态规划专题,你的笔记里可以整理出“背包问题从二维到一维滚动数组优化的过程”“最长递增子序列怎么从O(n²)优化到O(n log n)”,这份笔记既是你的知识库,也是考前复习的提纲。

第三个习惯是错题复盘。每周抽一天回顾本周做错的题,先不看答案自己重新写一遍,然后问自己:当时为什么错?是没理解题意、边界没想到、还是解法选错了?把错误原因写下来,之后定期翻看。我见过太多人同一道题刷了三遍还是错在同一个地方,不反思只刷题,效率非常低。

我还想特别说一句:押题不如押知识网。2016年滴滴这套题里的考点,到今天依然是各大厂笔试面试的核心。数组指针、链表反转、二叉树遍历、进程线程、TCP握手,这些东西不会因为技术迭代而过时,因为它们是计算机科学的基石。真正应该做的,是把这些基础知识点串成一张网,而不是赌今年会考哪道原题。

6. 对这套题的整体复盘与实战心得

这套题刷完之后,我最大的感受是:它的难度不在于单个题目的深度,而在于知识面的广度。你可能精通算法,但操作系统选择题照样丢分;你可能网络基础扎实,但C语言指针题依然困惑。所以准备这类笔试,拼的是谁的基本盘更均衡,谁更少有明显短板。

我建议在正式投递简历前,先做两套历年真题模拟。严格按照真实笔试的时间限制和流程来做,不要中途查资料,不要延长作答时间,模拟完再复盘。我第一次模拟时,选择题花掉了40分钟,编程题只剩40分钟,最后只完整写出了1道编程题。第二次模拟时调整了策略,编程题写了2道半,感觉完全不一样。模拟的意义不是做对多少题,而是提前暴露你的时间分配和答题习惯问题。

复盘时还有一个容易被忽略的点:留意你自己在选择题上反复纠结的题目类型。如果你每次都在TCP状态或者指针偏移上卡住,就把这类题整理成一个专题集中突破。这种定向补弱比大面积刷题更快见效。

回到这套“滴滴出行2016研发工程师笔试题(一)”,坦白讲,它并没有特别炫技的题目,所有的坑和考点都在基础范围内,但它完整地勾勒了那个时代互联网公司研发岗的能力画像:语言基本功扎实、数据结构敏感、算法思维清晰、系统知识够用。这四条到现在依然成立。如果你能把这份试卷的每一道题都吃透,把背后的知识点连成体系,那么走进任何一家公司的笔试考场,你都会更有底。

最后分享一个我自己的小习惯:笔试前一天的晚上不刷题,只看自己的思维导图和错题笔记,提纲挈领地过一遍知识框架。带着“我已经系统准备过”的状态走进考场,比临时抱佛脚刷几道新题有用得多。笔试准备是一个长期积累的过程,不急不躁,把基本功练扎实,你的代码和思路自然会替你说话。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询