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

资讯详情

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

滴滴研发笔试题解析:覆盖数组指针、HashMap、算法与操作系统全考点

滴滴研发笔试题解析:覆盖数组指针、HashMap、算法与操作系统全考点 在技术社区混久了你会发现一个有意思的现象真正经得起时间考验的往往不是当年被吹上天的框架和中间件而是那些看起来朴素的基础题。我最近翻到一份滴滴出行2016年研发工程师的笔试题一本来以为是考古结果越做越觉得值得聊。滴滴那会儿正处于业务高速扩张期招人标准在业内是出了名的“既要广度又要深度”所以这份笔试基本能代表当年互联网公司校招研发岗位的典型风格语言基础、数据结构与算法、操作系统与Linux、再加一道综合设计覆盖面很广。这类题目有意思的地方在于它考验的不是你会不会某个框架而是你计算机基础是否扎实。我见过不少人简历写得很漂亮项目经历花团锦簇但一做到数组指针、链表反转这种题就露馅了。反倒是一些平时不怎么刷题、但科班基础很牢固的同学在这类卷子上拿分很稳。原因很简单基础知识这东西没有捷径你理解到什么程度考场上就表现出来什么程度。这篇文章我就把这份卷子涉及的考点拆开揉碎讲一遍。我不打算只给答案而是连“为什么这么考”也一并说清楚。内容会覆盖数组与指针、Java语言特性、算法与数据结构、操作系统与Linux常见命令、以及综合题的设计思路适合准备校招笔试的同学也适合想自查一下基础功底的在职开发。1. 考题概览与知识点分布1.1 这份卷子的整体结构从题目设置来看2016年滴滴这套研发笔试题采用的是典型的“选择题简答/编程题附加题”结构。选择题占了大概百分之六七十的分值覆盖范围非常宽C语言/Java语言特性、数组与指针、进程与线程、内存管理、网络协议、数据库基础都有涉及。简答和编程题则集中在算法与数据结构上一般是一道链表操作、一道字符串处理、一道排序或者查找。最后那道附加题往往是系统设计类的开放性题目比如怎么设计一个司机乘客匹配模块、怎么做订单派单策略。有个细节值得注意这套题是研发岗位统一卷不像后端、前端、算法是分开的。所以它的考察侧重明显偏向通用计算机基础而不是特定技术栈。这意味着不管你是面Java岗还是C岗数组指针、操作系统、网络这些CS核心知识都是绕不开的。很多同学栽跟头就是在这一关平时写业务代码用不到指针用不到内存布局就觉得不用学结果一到笔试就现形。1.2 从考点分布反推能力要求如果把这份卷子的考点整理成一个能力模型大致可以分为三层。最底层是语言基本功包括C/C的指针与内存模型、Java的集合与并发机制这一层考察的是“你会不会写代码”。中间层是算法与数据结构包括链表、字符串、二叉树、排序查找这一层考察的是“你能不能写出高效的代码”。最顶层是系统观包括操作系统原理、网络协议、以及架构设计这一层考察的是“你写的代码放在大规模系统里能不能跑得稳”。有意思的是这三个层次和滴滴实际业务特点是对应的。作为出行平台滴滴的核心系统是高频、高并发、地理位置强相关的后端服务需要处理海量的司机位置上报和订单匹配请求。所以笔试中对集合类、HashMap并发问题、分布式锁这些知识点的偏爱本质上就是在筛选“能hold住大规模分布式系统”的候选人。理解这一点你就知道复习的时候应该把精力押在哪里而不是盲目刷题。2. 语言基础数组指针与Java高频考点2.1 数组和指针最容易被低估的送分题数组和指针是这套题里几乎必考的内容而且考得非常细。原因很简单C/C这门语言的精髓就在指针和内存管理上。我印象里这类题通常有以下几种考法。第一种是数组名与指针的关系。很多人只记住了“数组名是常量指针”这句话但一做题就错。比如int arr[5]问arr和arr的区别。其实arr是首元素的地址类型是int*而arr是整个数组的地址类型是int(*)[5]。两者数值相同但含义完全不同。arr1跳过一个int4字节arr1跳过整个数组20字节。这个考点几乎每年都出现但正确率一直不高。第二种是指针数组和数组指针的辨析。int *p[5]和int (*p)[5]一个是指针数组一个是指向数组的指针。区分方法很简单看变量名先和谁结合p先和[]结合就是数组数组元素是指针p先和*结合就是指针指向一个数组。在答题的时候我建议先写出类型推导过程再讲结论这样即使结论错了步骤分也能拿到。第三种是函数指针。比如让你写一个回调函数的声明或者用函数指针实现一个简单的计算器。这个知识点本身不难关键是格式容易写错。正确写法是int (*func)(int, int)注意括号不能省。这里有个经验笔试遇到指针相关的题不要急着看选项先在草稿纸上把类型画出来数组画成方块指针画成箭头图和图之间连线答案基本就出来了。注意C/C笔试中指针题分值不大但性价比极高。因为这类题套路固定只要把“数组与指针的区别”、“指针数组与数组指针”、“函数指针”三个模型吃透大部分指针题都能秒杀。2.2 Java高频考点从String到HashMapJava方向的题目在这套卷子里占比也很大尤其是在选择题部分。考察点集中在几个高频区域。第一个是String、StringBuilder、StringBuffer三者的区别。这个是面试八股文里的常青树了但笔试里它会换个马甲考给你一段字符串拼接的代码问创建了多少个对象。我记得有个经典题目String s new String(abc)创建了几个对象答案是两个一个是在常量池中的abc一个是堆中的String对象。如果面试官再追问一句“那String s abc呢”那就是一个只在常量池。这类题考察的是JVM内存模型所以复习的时候不要只背结论要把常量池、堆、栈的关系搞清楚。第二个是HashMap。2016年那会儿Java 8刚普及不久HashMap的考点主要集中在底层数据结构数组链表Java 8之后是数组链表红黑树、为什么用红黑树链表过长时查询退化为O(n)红黑树能把复杂度降为O(log n)、扩容机制默认负载因子0.75扩容时重新计算哈希并迁移节点。这些内容在笔试中通常以选择题或简答题出现难度不高但需要你能说清楚原理。第三个是线程与并发。synchronized和ReentrantLock的实现区别、volatile的可见性和禁止指令重排的作用、ThreadLocal的内存泄漏问题这几位都是笔试常客。答题的时候我的建议是不要只写结论最好能联系一个具体场景。比如问volatile能保证原子性吗答案是能保证可见性和有序性但不能保证原子性。然后举例说明两个线程同时对volatile变量做count最终结果还是会丢更新。这么一答改卷的人一眼就知道你是真懂不是背的。2.3 语言基础题的答题策略语言基础部分虽然知识点碎但真正考场上拼的其实是两点准确度和速度。准确度容易理解会就是会不会蒙的概率很低。速度就讲究技巧了选择题不要纠结不确定的先标记做完后面的题再回头细想。我见过太多人卡在一道指针选择题上花掉十五分钟结果后面算法大题没时间写这是典型的本末倒置。另外要特别提醒一个常见误区不要因为自己是Java方向就完全放弃C/C题。这套卷子里C语言相关的题目很可能占到三分之一以上因为历史原因当时互联网公司对候选人C语言功底依然比较看重。哪怕你只用Java也建议把指针、内存管理、结构体这些基础概念过一遍至少选择题要能做出来。这不难花两个晚上就能补上。3. 算法与数据结构笔试的隐形分水岭3.1 链表与字符串笔试必考的两大王牌算法题部分链表操作和字符串处理是出现频率最高的两类题型。链表题考的是指针操作的熟练度字符串题考的是边界条件的把控能力。这两类题很能反映一个人的代码基本功所以大厂笔试基本都会出。链表最常见的题目是反转链表。这道题看起来简单但现场写code的时候递归版和迭代版都能写对的人其实不多。我给的参考答案是迭代法public ListNode reverseList(ListNode head) { ListNode prev null; ListNode curr head; while (curr ! null) { ListNode nextTemp curr.next; curr.next prev; prev curr; curr nextTemp; } return prev; }这道题考察的核心就一个在修改curr.next之前必须先用临时变量保存住原来的next否则链表就断了。我见过不少人在这一步丢掉指针然后整道题崩盘。另外写完之后养成检查两个边界条件的习惯空链表和只有一个节点的链表确认代码都能正确处理。字符串题里判断回文串、找最长回文子串、字符串匹配都是高频题。笔试的难度不会到KMP那么深除非是算法岗但要求你能写出O(n^2)的动态规划解法或者至少能用双指针法解决回文判断。比如这道经典题给定一个字符串找出最长回文子串。一个可靠的解法是“中心扩展法”思路是遍历每个位置把它当作回文中心向两边扩展。要注意的是回文中心可能是一个字符奇数长度也可能是两个字符之间偶数长度所以要分两种情况处理。这里我想多说一句算法题能不能AC很大程度取决于你平时有没有形成“边界条件检查”的肌肉记忆。很多同学刷题时能写出主体逻辑但忽略了空指针、数组越界、字符串长度奇偶这些边界情况提交后发现用例没过这是非常可惜的。我自己的习惯是写完code后立刻在脑子里跑三个用例空输入、最小输入、正常输入养成这个习惯能少丢很多分。3.2 排序查找从原理到手写代码排序和查找也是笔试的重点尤其是快速排序和二分查找几乎可以说是“必考二选一”。不是考你用库函数而是要你手写实现并分析时间复杂度。快速排序的写法建议背熟一种并且能解释清楚为什么快。核心思想是“分治分区”每次选一个基准元素把小于基准的放左边大于基准的放右边然后递归处理左右两个子数组。平均时间复杂度是O(n log n)最坏是O(n^2)最坏情况发生在每次选的基准都是最大或最小元素的时候。一个常见的优化是“三数取中”从首、中、尾三个位置取中间值作为基准能有效避免最坏情况。二分查找的代码容易写错的地方在于边界值的判断。这里给出一个不容易出错的模板public int binarySearch(int[] nums, int target) { int left 0, right nums.length - 1; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) { return mid; } else if (nums[mid] target) { left mid 1; } else { right mid - 1; } } return -1; }注意我写的是left (right - left) / 2而不是(left right) / 2。后者在left和right都很大时可能溢出这个细节在笔试中偶尔会作为坑出现。还有循环条件是left right如果写成了会漏掉left right时那个元素的检查。3.3 算法题作答的现场思路算法题在笔试里通常分值最高也是最容易拉开差距的环节。我自己的作答流程是四步先花两分钟读题确认输入输出范围再花五分钟想暴力解法从暴力解出发推导能否优化然后写代码边写边注释关键步骤最后跑用例验证包括正常情况和边界情况。很多人上来就想最优解结果卡在优化思路上半小时一动不动。我的经验是先把暴力解写出来哪怕复杂度是O(n^2)先把分拿到再考虑怎么优化。在笔试评分中往往有“部分正确”的分数一个能跑通的暴力解比一个没写完的最优解要强得多。如果你写出了暴力解还有时间再从“空间换时间”、“双指针”、“哈希表”这几个方向去想优化。提示笔试中时间管理极其重要。建议按“分值/时间”来分配分值高的题分配更多时间但单题不要超过总时长的三分之一。如果你在一道题上卡了超过20分钟果断先做下一道回头再补。4. Linux与操作系统题型的解题要点4.1 高频命令与文件系统Linux相关的题目在研发岗笔试中几乎从不缺席。这部分考得比较基础但范围很广常用命令、文件权限、进程管理、网络排查都有涉及。选择题里出现频率最高的是grep、awk、sed、find、ps、top、netstat这几个命令的用法。比如给你一个需求查找某个目录下所有包含“error”的日志文件你会用什么命令常规答案是grep -r error /var/log/。-r表示递归搜索这是最快能想到的解法一般能得分。但如果题目问“如何统计每个IP的访问次数”那就需要用到awk了。一个标准的答案是awk {print $1} access.log | sort | uniq -c | sort -nr这串命令其实考了四个知识点awk取列、sort排序、uniq统计、sort降序。遇到这种题建议把每一步的输出都在脑子里过一遍不要直接写最终结果逻辑越清楚越不容易错。文件系统方面软链接和硬链接的区别也是高频考点。软链接symbolic link相当于Windows里的快捷方式是一个独立的文件里面存放的是目标文件的路径硬链接hard link则直接指向同一个inode相当于给同一个文件起了多个名字。删除源文件后软链接会失效硬链接不受影响。这个知识点不难但考得很细建议把inode的概念彻底搞懂遇到类似题目基本就是送分。4.2 进程线程与内存管理核心概念操作系统选择题里进程与线程、死锁、内存管理是三大块。每一块都有一些“必须拿下”的核心知识点。进程和线程的对比是必考题。核心差异在于进程是资源分配的基本单位线程是CPU调度的基本单位。进程之间地址空间相互隔离线程共享所属进程的地址空间。挂在这道题上的人往往是只背了结论没理解“为什么线程切换比进程切换代价低”——因为线程切换不需要切换地址空间所以TLB等缓存都不用失效。能说出这一层才算真正理解了。死锁这块四个必要条件互斥、持有并等待、不可剥夺、循环等待几乎是必背内容。但笔试常考的不只是让你列举条件而是给你一个场景让你判断是否会发生死锁或者问怎么预防。实用的答题思路是先判断是否满足四个必要条件再提出打破某个条件的方案。比如一次性申请所有资源可以打破“持有并等待”按序分配资源可以打破“循环等待”。内存管理部分分页和分段、虚拟内存、页面置换算法是核心。页面置换算法中LRU最近最少使用考得最多偶尔也会考FIFO和Clock算法。这种题通常会给出一个访问序列让你模拟缺页中断过程。没有捷径老老实实画表推导但推导过程中要注意内存已满且访问页不在内存时才产生缺页已在内存中的访问不会触发置换。我见过有人把“命中时的页表更新”也算作缺页白白丢分。4.3 综合设计题的答题套路这套卷子末尾的附加题一般是系统设计类也可能是场景设计题。比如让你设计一个简化版的功能模块要求画出架构图、说明数据存储选型和核心接口设计。这类题看着吓人其实有固定答题套路。我建议按以下顺序展开先明确需求边界一句话说清楚这个模块要解决什么问题再划分功能模块把核心流程拆成三到五个环节然后选型说明用什么存储MySQL还是Redis、什么消息队列最后画核心接口把输入输出定下来。以“司机乘客订单匹配”为例需求边界是乘客发单后系统快速找到附近合适的司机。功能模块可以拆成乘客发单、司机位置上报、匹配计算、订单推送。存储选型上司机位置数据实时性要求高应该用Redis的GEO数据结构来存储订单数据需要持久化用MySQL。接口设计方面核心是submitOrder和pushOrder两个接口。按照这个套路写下来哪怕方案不够完美但结构清晰、逻辑完整比想到哪写到哪的答案得分要高得多。5. 常见问题与备考避坑实录5.1 时间分配笔试翻车的头号原因我每年校招季都会看到不少人发出“题目都会但没写完”的感叹这背后几乎都是时间分配出了问题。笔试题量大、分值分散如果把时间过多押在难题上前面的基础分反而不保。从这套题来看我建议的时间分配是选择题控制在每道90秒以内总用时不超过总时长的40%编程题每道20到25分钟留出最后10分钟检查。这样做的好处是即使编程题没完全AC前面基础题的分已经拿到了总分不会太难看。反过来如果在一道算法题上死磕了40分钟导致后面8道选择题没做那损失就大了。5.2 细节丢分会做的题怎么拿满分很多同学出来对答案发现“这题我会啊怎么错了”原因往往出在细节上。比如编程题没有处理空指针、循环条件的边界写错、输入输出格式不符合要求、没有写注释导致改卷人看不懂思路这些都会成为扣分点。我特别想说一下“写注释”这个事。笔试是人工改卷至少简答题和编程题是的。一个写了清晰注释的代码和一个没有注释的代码在改卷人眼中的可读性差距是很大的。也不需要对每一行都注释但关键算法步骤加一句说明判卷人就能快速理解你的意图即便有小错也更容易给步骤分。还有一个细节选择题尽量别空着。这类笔试通常不倒扣分即使不会也要凭经验排除一两个选项后蒙一个提高命中率。但这里有个前提你得先把会做的都做了时间充裕再来蒙。5.3 备考建议从真题出发往深处打最后聊一点备考思路。如果你正在准备类似的工作岗位笔试我的建议是不要追求刷题数量而要追求“每道题都能讲清楚原理”。比如链表反转这道题你如果能做到闭着眼写出迭代版和递归版能解释清楚两种方式的空间复杂度差异能说出递归版在链表很长时有栈溢出的风险这道题才是真正吃透了。资源方面LeetCode的“热题100”和“剑指Offer”就足够了没必要贪多。经典教材方面C语言部分看《C程序设计语言KR》足够Java部分看《Java编程思想》或《Effective Java》都行操作系统看《现代操作系统》或国内教材都可以。知识体系比题目数量重要如果你能把一个知识点从原理讲到应用场景再讲到坑笔试基本难不倒你。我自己的体会是这类研发工程师笔试题本质上考的是你在计算机基础这条路上走了多远。会这些内容不代表你能写好业务代码但基础扎实的人学习新框架、解决线上问题的速度通常更快。所以别把刷题当成应付笔试的临时任务它其实是你查漏补缺、夯实内功的绝佳机会。认认真真把每一道题背后的知识点弄懂你会发现后续的面试和工作中这些基础会反复回来帮到你。
返回列表