面灵AI→

美团 后端开发一面:手撕阶乘与合并有序数组,HashMap 追问

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

一面

  1. 手撕:n 的阶乘
  2. 手撕:合并有序数组
  3. SQL:查到某门课的平均值,按平均值和课程号排序
  4. 设计模式有哪些?用过哪些?
  5. HashMap 为什么线程不安全?怎么保证安全?
  6. 头插法和尾插法有什么区别?
  7. Java 里有哪些容器?
  8. 聊项目:难点是什么?怎么解决的?
  9. 聊实习:难点是什么?怎么解决的?

《参考解析》

  1. HashMap 线程不安全要分版本讲,才显得你真读过源码:JDK 7 的头插在并发扩容时可能让链表成环,之后的 get 会死循环打满 CPU;JDK 8 改成尾插后成环问题基本消失,但仍有并发 put 覆盖丢数据、size 统计不准、扩容期间读到中间状态这几类问题。保证安全的三条路:ConcurrentHashMap(首选,JDK 8 用 CAS 加 synchronized 锁单个桶,粒度细)、Collections.synchronizedMap(一把大锁,只是包了一层)、Hashtable(全表锁,已经过时)。会写「并发场景别用 HashMap,读多写少的配置缓存用 ConcurrentHashMap,需要复合操作时用它的 computeIfAbsent」,比背结论更完整。

  2. 头插法与尾插法:先把问的对象确认清楚:这题可能问的是 HashMap 扩容时的链表插入方式,也可能问的是链表本身的建表方式。按前者的答法是:头插实现简单、插入 O(1),但在并发扩容下会反转链表顺序进而成环;尾插保持原有相对顺序、扩容后不再成环,代价是要多维护一个尾指针。按后者的答法是:头插不用遍历、天然逆序,尾插要走到表尾、保持输入顺序,单链表删除某个节点时头插法少一步。答题时先问一句「您指的是 HashMap 扩容的插入方式还是链表建表」,把模糊问题钉住,本身就是加分动作。

  3. SQL 那题先写分组再写排序:按课程分组的平均分是 select course_id, avg(score) as avg_score from score group by course_id order by avg_score desc, course_id asc。要注意三点:order by 里可以用别名、也可以直接写聚合函数;排序字段要有明确次序(平均值降序、课程号升序),题目说「按平均值和课程号排序」就是在考你有没有写全第二排序键;聚合字段没在 group by 里出现(only_full_group_by 模式)会直接报错,别写成 select *。被追问的话,再补一句按平均分筛选用 having 而不是 where。

  4. 手撕两题考的是边界和代码习惯,不是难度:n 的阶乘要先问清范围——int 到 13 就溢出,long 到 20 也到顶,超过就必须上大数(Java 的 BigInteger,C++ 手写高精度数组),能主动问这一句就不再是背模板;实现上写递归要说明栈深风险,写迭代要给出溢出处理。合并有序数组的标准解法是双指针加一个结果数组,从前往后逐个比较取小,注意一个数组先走完后要把另一个剩下的直接搬过去,空数组和长度不等是必测边界。如果面试官要求原地合并(nums1 尾部留了空位),改用从后往前填的三指针写法,避免覆盖未比较的元素——能把这两种写法都讲清楚,比写得多快更有价值。

  5. 设计模式和 Java 容器要答「用过什么、解决什么问题」:设计模式别只报 23 个名字,按场景归类——创建型(单例、工厂、建造者)、结构型(代理、适配器、装饰器)、行为型(策略、模板方法、观察者、责任链),再各举一个自己项目里的例子,比如策略模式替换掉一长串 if-else、模板方法统一多个数据源的导入流程。被追问「Spring 里用了哪些」,可以说 Bean 工厂与 ApplicationContext、AOP 用的动态代理(JDK 代理与 CGLIB)、JdbcTemplate 用的模板方法。Java 容器按 Collection 与 Map 两条线画:List(ArrayList 数组、LinkedList 链表、Vector 已过时)、Set(HashSet、TreeSet、LinkedHashSet)、Queue(ArrayDeque、PriorityQueue)、Map(HashMap、LinkedHashMap、TreeMap、ConcurrentHashMap),说清各自的底层结构和选型判据即可。

  6. 项目和实习的难点要落到「你的判断」:这题几乎每场都会问,模板是四段——背景约束、难点是什么(技术难点还是协作难点的区分要说清)、你试过什么方案、最后怎么定的以及结果。最容易被追问穿的是「这个难点为什么难」,所以要准备一个能讲透的点:比如一次线上问题的定位过程、一次性能优化的量化收益、一次方案被推翻后的重新选型。两个项目不要都讲成「用了什么框架」,第二个要体现难度递增。

  7. 答得顺却收到感谢信,要复盘但不能归因错:技术面反馈好却挂掉,常见原因是 HC 已满或排序后被更匹配的人挤掉、岗位方向与你的经历错配、或者你自己没察觉的表达问题(对岗位兴趣不足、对业务理解停在表面)。能做的事是把可控项做扎实:把这场的问题清单记下来,补上没答好的技术点;投递时按 JD 调整简历顺序,把最对口的一段经历放最前;面试快结束时用反问确认团队在做的事,并简短表达你为什么合适。把结果当反馈而不是判决,比反复琢磨公平性有用。