ARTICLE DETAIL

资讯详情

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

百度Java笔试复盘:从HashMap到算法的考点拆解与备考指南

百度Java笔试复盘:从HashMap到算法的考点拆解与备考指南 1. 先看卷面结构2020第一批到底考了哪些题型1.1 题型构成和分值分布我参加的是2020校招百度Java研发工程师岗的第一批线上笔试当时用的在线笔试平台支持摄像头监控和实时编译总时长120分钟。整张卷子给我的第一感受是题型很全但没有偏题怪题。印象里大致分为单选、多选、填空、简答和两道在线编程题。单选大概15道多选5道填空3道简答2道编程2道。如果按分值估算单选和多选加起来能占到45%左右简答占20%左右编程题占25%剩下的填空占10%。具体数字不一定精准但比例不会差太多。为什么要先聊卷面结构因为很多同学在准备大厂笔试时容易陷入一个误区觉得算法题是唯一重点基础题随便看看就行。但百度这场笔试恰恰是基础题占了半壁江山。单选多选里的内容几乎覆盖了Java集合、并发、JVM、操作系统、数据库和网络简答题还要你写出设计和排查思路。也就是说算法只是筛选条件之一计算机综合基础和Java功底才是决定你能不能进面试的关键。如果你只刷LeetCode不补基础大概率前面选择题就会丢掉大把分。1.2 从热搜词看考察重点的变化我在考前搜过大量“Java面试八股文”“百度Java面试题”也看了很多关于HashMap、快速排序、lambda函数、枚举类型的帖子。后来我发现热词里的内容不等于考卷上的内容但热词背后反映的考点分布很有参考价值。比如HashMap原理、JVM内存、线程池参数、TCP三次握手这些话题在任何一年的大厂笔试里都是高频点。2020第一批的Java卷表面看考的是具体知识点实际上是在考“你学习的时候有没有把源码和底层机制读透”。就拿HashMap来说网上到处是“底层是数组加链表、扩容因子0.75”这类口诀但如果卷子问“链表转红黑树的阈值为什么是8”你只背口诀是不够的。搜索热词只能帮你圈定复习范围不能替代源码阅读和做题复盘。真正有效的备考是把热词背后的每个知识点都往深处挖一层。2. Java考点逐个拆HashMap、线程池、JVM是铁打的三角2.1 集合框架不看源码就会翻车的题百度2020第一批Java卷的选择题里集合框架绝对是C位。我记得好几道题都在围绕HashMap做文章比如JDK 1.8中HashMap的put流程是什么扩容时链表会怎样拆分ConcurrentHashMap在并发场景下是怎么保证线程安全的这类题目如果不看源码真的只能靠蒙。这里我把HashMap最核心的底层逻辑重新捋一遍。存储结构是数组加链表加红黑树put的时候先对key的hashCode做扰动运算然后根据数组长度取模找到桶位。如果桶位上没有元素就直接放如果有元素就根据key是否相同决定替换还是追加到链表尾部。链表长度达到8并且数组长度大于等于64时链表会转成红黑树。加载因子0.75是为了在空间和时间之间取一个平衡太大会增加碰撞概率太小会浪费空间。笔试里容易被坑的点是HashMap允许key和value为null而Hashtable不允许多线程环境下HashMap不是线程安全的JDK 1.7的头插法在扩容时可能产生循环链表1.8改成尾插法后同样不建议直接用应该使用ConcurrentHashMap。ConcurrentHashMap在JDK 1.8中放弃了分段锁改成了CAS加synchronized对每个桶节点加锁锁粒度更细并发度更高。这些细节如果能脱口而出选择题基本就稳了。2.2 并发编程线程池参数和锁的经典问法并发题在卷子里也占了不小的比例。百度喜欢考线程池参数几乎是约定俗成的。ThreadPoolExecutor的核心参数有7个核心线程数、最大线程数、空闲存活时间、时间单位、任务队列、线程工厂、拒绝策略。具体执行逻辑是请求进来先判断核心线程是否满了没满就创建核心线程满了就进队列队列也满了才创建非核心线程直到最大线程数再满就触发拒绝策略。卷子上很可能会给你一个具体场景比如核心线程2、最大线程5、队列容量10然后一次性提交20个任务问最终会有多少个线程在处理。很多人一上来就答5个实际上队里先放10个再来3个把核心线程和非核心线程补满剩下5个触发拒绝策略所以最终是5个线程在处理任务其中2个核心线程加3个非核心线程。这个例子说明线程池的调度不是简单的“来一个任务就创建一个线程”必须把队列容量也算进去。还有一类高频题是synchronized和ReentrantLock的区别。常规回答包括前者是JVM层面实现后者是JDK API前者支持自动释放锁后者需要手动释放后者支持公平锁、可中断、多个条件队列。笔试选择题还喜欢考volatile它只保证可见性和有序性不保证原子性。比如volatile修饰的计数器在并发自增时结果仍然会小于预期因为i不是原子操作。这种细节一旦理解透单选题基本不会错。2.3 JVM与内存排查OOM的思维链条JVM在百度笔试里不会缺席。最基础的是运行时数据区堆、虚拟机栈、本地方法栈、方法区、程序计数器。选择题常考“哪些线程共享哪些线程私有”堆和方法区是线程共享的虚拟机栈、本地方法栈、程序计数器是线程私有的。还有一种问法是“创建对象时内存怎么分配”这需要知道指针碰撞和空闲列表以及TLAB这个东西。搜索热词里出现过“java: outofmemoryerror: insufficient memory”很多人看到这个报错会以为是堆内存不足其实不一定。JVM有几种常见的OOM堆溢出是在new对象时抛OutOfMemoryError: Java heap space栈溢出一般抛StackOverflowError元空间溢出会报Metaspace还有一种native memory不足会报insufficient memory。笔试里碰到这种题不能一上来就说加堆内存要先判断是哪块区域出问题。正确的排查思路应该是先看错误日志如果是Java heap space用jmap生成堆转储再用MAT分析哪些对象占据了大部分内存如果是元空间检查是否有大量动态生成类如果是native memory可能需要去查DirectByteBuffer或者线程数量。百度考这个点本质上不是要你当运维而是检测你有没有排查线上问题的大局观。答题时把“现象—定位—工具—修复”这条链路写清楚简答题分数就不会低。2.4 语法细节lambda、枚举、运算符的隐藏考点Java岗位的笔试还会夹杂一些语法细节题很多人复习时容易忽略。比如lambda表达式表面问怎么用实际考的是函数式接口和变量捕获。lambda本质上是对匿名内部类的一种简化但它并不是简单的语法糖编译器会生成invokedynamic指令。选择题爱问“lambda表达式能访问哪些变量”答案是可以访问局部变量但该变量必须是隐式final的因为lambda表达式只是一个代码块它不能修改外部局部变量。枚举也需要特别注意。在Java里枚举是用enum关键字定义但编译之后会变成一个继承java.lang.Enum的final类构造器是私有的。枚举可以定义字段、方法、抽象方法还可以实现接口。有些选择题会问“枚举可以继承某个类吗”答案是不能因为已经隐式继承了Enum。这个点很多人背了但没理解导致笔试时被绕进去。运算符和表达式更是经典送分题。三目运算符的类型转换规则、位运算符的优先级、短路与和短路或的区别都是单选填空的常客。比如“int a 5; boolean b (a 3) (a 5);”最后a是多少很多人答6实际a还是5因为短路与表达式前半部分为真后半部分不会执行。这类题目不难但特别检验细节。3. 算法题复盘字符串、DP、图论的实战场3.1 字符串题无重复最长子串的变体百度2020第一批的编程题让我印象最深的是有一道字符串相关的题核心思路和“最长无重复字符子串”很接近。题干描述可能是“给定一个字符串找出其中不含有重复字符的最长子串长度”这种题在LeetCode上是第3题看起来简单但笔试环境里写起来容易漏边界。标准解法是滑动窗口维护一个HashMap记录字符最近出现的位置遇到重复字符时把左边界移动到重复字符之前出现位置的下一位。以下是Java实现public int lengthOfLongestSubstring(String s) { int left 0, maxLen 0; MapCharacter, Integer map new HashMap(); for (int right 0; right s.length(); right) { char c s.charAt(right); if (map.containsKey(c)) { left Math.max(left, map.get(c) 1); } map.put(c, right); maxLen Math.max(maxLen, right - left 1); } return maxLen; }这里有几个笔试高频坑。第一输入可能为空字符串要在开头就判断。第二map.get(c)返回的是旧坐标可能小于当前left所以要用Math.max来更新left不能直接让left等于旧坐标加一。第三输出的是最长长度不是最长子串本身读题千万别看错。3.2 动态规划从递归到递推的套路另一道编程题我印象里偏动态规划很可能是背包或者最长公共子序列的变体。动态规划题的难点在于状态转移方程怎么想。如果你对“最优子结构”和“重叠子问题”这两句话有感觉就能判断该用DP。我建议笔试时先写递归版本把思路理清楚再改成递推。比如最长公共子序列两个字符串的dp[i][j]表示第一个字符串前i个字符和第二个字符串前j个字符的最长公共子序列长度。如果字符相等dp[i][j] dp[i-1][j-1] 1否则取dp[i-1][j]和dp[i][j-1]的较大值。初始化时要注意dp[0][j]和dp[i][0]都为0。笔试时间和工程开发不一样不需要追求最极致的优化。如果空间复杂度能降就降但不能因为优化引入bug。我的习惯是先用二维数组把答案写对如果有余力再改成滚动数组。在牛客网或者赛码网这种在线OJ上答案正确性比代码优雅更重要。很多人倒在了“想用一个很花哨的状态设计”上最后写不完。3.3 排序与边界冒泡、快排和“看似简单”的陷阱百度卷里的基础算法题不会让你手写一整套排序但选择题喜欢考排序的延伸内容。比如快速排序的平均时间复杂度是O(nlogn)最坏是O(n^2)稳定性上快排是不稳定的归并排序是稳定的Arrays.sort()对基本类型用的是双轴快速排序对对象类型用的是TimSort。这些都属于“看似知道一考就错”的知识点。快速排序的partition过程是笔试手写题常客。经典写法是选一个基准值两个指针从左右往中间找左指针找比基准大的右指针找比基准小的然后交换。边界条件是当left等于right时停止最后把基准值换到中间。这个代码写起来不算长但如果partition返回值的位置理解错整个递归就会出问题。我印象里有一道单选考冒泡排序的优化如果某一轮遍历发现没有发生交换说明数组已经有序可以提前结束。这个优化用了一个boolean标志位。它的意义是让最好情况时间复杂度变成O(n)在笔试里算是一个“惊喜点”。记住这些细节不仅对选择题有用对面试手撕排序也有帮助。3.4 做题顺序和时间分配编程题在笔试电脑上做时间压力很大。我的建议是先用2到3分钟读题理解输入输出格式和边界条件然后决定用什么算法。如果5分钟内没有完整思路先写暴力解保底比如直接双重循环虽然只能拿部分分但总比交白卷强。暴力版本跑通之后如果时间充足再优化。还有一点很关键务必要先处理边界输入。比如字符串可能为空数组长度可能是1目标值可能不存在。在线编程题的判题系统会跑很多隐藏用例很多人的思路是对的就因为没处理数组越界而得了0分。我在真实笔试里就吃过这个亏一道字符统计题没判断输入为空导致前几个样例通过但后面全挂。写完代码后先把这些边界用例手动过一遍比盲目提交稳得多。4. 网络、数据库和智力题Java岗也会被问到的周边地带4.1 SQL索引优化送分题怎么稳拿数据库在Java岗笔试卷里出现的概率极高百度2020第一批也不例外。印象里有一道SQL题是给两个表一个是员工表一个是部门表要求查每个部门的平均薪资并排序。这类题只要会GROUP BY和JOIN就能写算是送分题。真正拉开差距的是索引优化的选择题。比如卷子可能会问一个表有联合索引(a, b, c)那么查询条件只有b和c时走不走索引答案是不走因为不符合最左前缀原则。另一种情况是a和c有索引条件走一部分索引然后在c上做过滤。这个知识点在数据库面试里出现过无数次但每次仍然有一批人答错原因是没有把“最左前缀”当成一个整体理解。还有回表和覆盖索引的概念。普通索引查到主键之后还要回主键索引再查一次这就是回表。如果查询的字段都包含在索引里就不用回表叫覆盖索引。笔试如果问“如何优化一条慢SQL”你可以先分析是否走了索引再看有没有回表最后看是否可以用覆盖索引。这个排查思路比单纯背“索引可以加快查询”要有用得多。4.2 TCP三次握手和HTTP状态码八股文要背到条件反射计算机网络在笔试里是必考项。百度2020第一批的选择题里至少有2到3道和TCP、HTTP相关。最经典的当然是TCP三次握手为什么是三次不是两次因为三次握手能确保双方的收发能力都正常同时防止旧连接请求突然到达后服务器白白建立一条连接。如果只有两次握手当客户端的一个延迟的SYN到达服务器时服务器会误以为客户端想建立新连接而产生资源浪费。HTTP状态码也经常考。200、301、302、403、404、500、502、504这些必须烂熟于心。尤其要注意502 Bad Gateway和504 Gateway Timeout的区别502是网关收到了后端服务器的无效响应504是网关在指定时间内没有收到响应。这两个状态码在排查线上问题时很容易混淆笔试选择题也很喜欢拿来挖坑。除了TCP和HTTPHTTPS的握手过程也是大厂笔试的常客。大致流程是客户端先发送ClientHello服务端返回证书和ServerHello双方协商密钥套件然后客户端生成预主密钥并用服务端公钥加密发送服务端用私钥解密最后双方各自计算出对称密钥。能把这个过程用几句话说清楚网络部分就能拿一个不错的分数。4.3 系统设计题没有标准答案但有标准结构百度2020第一批的简答题里我印象中有一道开放题大概是问如何设计一个短链接系统或者如何设计缓存方案。很多人看到“设计”两个字就慌不知道从哪里下手。其实系统设计题在笔试阶段不会要求你画完整架构图它只是想看你的分析思路是否有条理。我总结了一个通用答题模板笔试现场可以直接套用。第一明确需求用户量多大QPS多少需要支持哪些功能。第二估算数据量如果每天新增一亿条短链接一年是多少条需要多大存储。第三设计接口包括生成短链接、跳转长链接两个接口。第四设计存储用一张表存短码和长链接短码生成方式可以用发号器或者哈希加冲突处理。第五考虑扩展缓存热点映射使用Redis减少数据库压力定期清理过期数据。简答题不需要写到能上生产环境的程度但一定要让阅卷人看出你有完整思考。哪怕你给出的方案不是最优的只要逻辑顺畅、覆盖了关键点得分就不会低。我最想提醒的是不要只写一两句话至少把“流量—存储—缓存”这条主线写完整。5. 考场上的坑编程环境、输入输出和心态管理5.1 在线IDE的输入输出陷阱在线编程题和本地IDE最大的区别是输入输出要自己处理。很多人在刷LeetCode时习惯leetcode已经给你定义好函数但百度笔试用的是牛客网或赛码网输入需要从System.in读取。有时候一道题给多组测试数据第一行是组数后面每行是具体数据。如果你只处理了一组测试用例就会挂。比如读取多行整数常见写法是Scanner sc new Scanner(System.in); while (sc.hasNextInt()) { int n sc.nextInt(); // 处理一组数据 }这里要注意nextInt和nextLine混用时的换行问题。读完数字后如果接下来要用nextLine读取字符串必须多调用一次nextLine把换行符吃掉否则会得到空字符串。这个细节我在真实笔试里踩过坑当时以为自己代码写错了排查半天才发现是readline多读了一个空行。这种问题一旦遇到特别浪费时间所以在平时练习时就该养成标准输入处理的习惯。5.2 编译器版本和代码规范在线OJ的Java环境一般是JDK 8或JDK 11考试时允许使用lambda表达式。但我不建议在任何编程题里写出太依赖语言特性的代码比如复杂的Stream流操作因为笔试平台一旦报编译错误查起来很麻烦。最稳妥的方式是用最基础的循环、数组和集合保证代码在任何JDK版本下都能编译通过。还有一个细节是类名和包名。在线OJ要求主类名必须是Main并且不能有package语句。有些同学在本地IDE里习惯了加package复制到在线编辑器后忘了删直接编译失败。这种扣分真的非常冤枉。另外输出格式也要严格一致比如要求输出两行结果你输出一行就算答案数值对也会判错。5.3 遇到不会的题怎么办再厉害的选手也会碰到完全没思路的题。2020第一批的Java卷里有一道多选我当时很犹豫因为选项里有两个都是“看似正确”的并发结论。面对这种情况我的建议是多选宁少勿多只选有把握的选项单选完全不会时也不要空着可以用排除法先去掉明显错误的选项。编程题如果真的没有思路一定先写一个暴力版本把能拿的部分分拿满。很多判题系统会按通过的测试用例数给分而不是要求全对。所以哪怕是O(n^2)的解法只要结果正确也能拿到一定比例的分。还有一个技巧把题目里给的示例输入输出先跑通至少确保理解正确再考虑优化。6. 备考策略以百度2020为样本怎么安排复习优先级6.1 分阶段复习基础—刷题—模拟如果你也打算冲击百度或者其他大厂的Java研发岗我建议把备考拆成三个阶段。第一个阶段是Java基础和计算机基础时间大概两周。重点复习集合源码、并发编程、JVM内存、数据库索引、网络协议。这个阶段不需要刷太多题目但要把核心概念理解透尤其是HashMap、线程池、JVM这三件套。第二个阶段是算法刷题时间三周左右。每天保持2到3道题的节奏按专题分类刷比如字符串、链表、二叉树、动态规划、图论。不要只刷LeetCode的hot100也要去牛客网做在线编程题适应自己处理输入输出的环境。百度笔试的算法题难度大致是LeetCode中等偏下所以把高频题型练熟就够了不需要纠结太多hard题。第三个阶段是全真模拟和错题回顾时间一周。找一套往年大厂笔试真题按考试时长和状态做一遍做完后逐题复盘。这个阶段重在模拟考场节奏锻炼时间分配能力。我当时参加百度笔试前用牛客网的模拟题练了三次每次都能发现自己在“输入输出”或“边界判断”上的问题。6.2 错题复盘的正确姿势很多人的刷题量很大但成绩提升很慢问题就出在不复盘。错题复盘不是把答案抄一遍而是要把每一道错题拆解成几个问题这道题在考哪个知识点我当时为什么错是知识点不知道还是知道但不会灵活用下次遇到类似题我应该怎么判断只要把这个链条写出来错题才有价值。我建议每个错题都整理到一个表格里字段包括题目来源、考察知识点、错误类型、正确思路、关联题目。这样考前复习时只需要看错误类型分布就能知道自己的薄弱环节。比如发现十个错题里有七个是动态规划的边界问题那下一个阶段就专攻DP边界而不是重新刷一遍全题型。6.3 针对百度风格的临场技巧最后分享几个针对百度笔试的临场技巧。第一多选和填空不要浪费太多时间遇到卡壳的先标记做完编程题再回来想。第二编程题写之前先在注释里写出思路比如“滑动窗口右指针移动左指针去重”这能帮你理清逻辑也方便自己检查。第三如果笔试时间允许最后一定要检查一遍代码里的循环边界和最大最小值尤其是数组长度为零的情况。我在实际笔试中发现大部分失分不是知识量不够而是考场状态和小细节出问题。比如有同学在写二维数组DP时把行和列搞反了有人用Scanner读取大量数据导致超时还有人没有处理重复输入。这些都不是高深难题只要提前模拟、提前踩坑完全能避免。最后说一个我自己的复盘习惯从考场出来之后趁记忆还热立刻把能记住的题目和选项都写进备忘录。后面再对着这个清单把每道题映射到对应的知识点和复习资料上。这个动作看起来简单但它能帮你把一次笔试转化为一份长期适用的复习地图。备考大厂没有捷径但把每一次真枪实战都变成自己的经验就是最有效的捷径。
返回列表