5年社招百度、阿里后端面试经验分享!
这是我的博主朋友云雨雪 2023 年底面试百度和阿里的部分原题,为啥不是全部呢?因为有些已经忘了,哈哈哈,毕竟已经过去半年了。
这篇不是纯分享面试题,而是附带分享了一些面试经验和技巧,学到就能直接拿来用,社招和校招都适用,写的很用心!

这篇面经分享会以我的好友云雨雪视角书写,可能会由于笔误不小心写成第一人称视角,请不要误会哦!
百度二面
百度是云雨雪面试的第一家公司,当时 JD(Job Description,职位描述)非常适配云雨雪的工作经历,并且 HR 也相当火热,无法拒绝,于是答应第二天晚上面试。百度的面试工具是如流,一个自研的会议软件,我记得桌面端自带一个写代码的插件,非常顶,目前体验上佳的视频会议软件,点个赞。面试部门是日志部门,除了基建还做业务方向的日志分析,部分大数据技术栈要求,和我的技术栈高度适配。由于是第一次面试大厂,忘了记录和复盘,太紧张了。
一面最后有道面试题,印象比较深刻,题目是:
有一个大文件,记录一段时间内百度所有的搜索记录,每行放一个搜索词,因为搜索量很大,文件非常大,搜索词数量也很多,内存放不下,求搜索次数最多的TopN个搜索词。
输入:大文件
输出:TopN搜索词列表
我的解答是:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.*;
/**
* 有一个大文件,记录一段时间内百度所有的搜索记录,每行放一个搜索词,因为搜索量很大,文件非常大,搜索词数量也很多,内存放不下,求搜索次数最多的TopN个搜索词。
* 输入:大文件
* 输出:TopN搜索词列表
*/
public class Baidu {
/**
* 输出TopN搜索词列表
*
* @param inputFile 输入文件
* @param n TOP N?
* @return TopN搜索词列表
* @decsription 该方法未考虑连所有不重复的词语也无法完全加载的情况,只能假设当前内存能存下所有搜索词(如果时间不够,暂时使用当前办法)
* TODO 来不及了,先写思路,海量数据问题通常采用分而治之的解决方法,面对上面连所有不重复词语都无法加载的情况
* 可以先加载一部分已装入wordCountMap的数据,对key也就是词语进行hash,写入到多个小文件中,这样相同key都会聚集在一个小文件 中
* 装载完成后对小文件中的数据读取,对相同key的数据相加,最后汇总所有小文件数据(还是有问题...)
*/
public static List<String> findTopNWords(File inputFile, int n) {
List<String> topNWords = new ArrayList<>();
Map<String, Integer> wordCountMap = new HashMap<>();
//读取文件
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile))) {
String line;
//一行行读取数据,避免一次性加载不了
while ((line = reader.readLine()) != null) {
//每行放一个搜索词,没说是不是句子,假设按照 aa bb cc对语句按照单词拆分
String[] words = line.split("\\s+");
for (String word : words) {
//单词对应次数+1
wordCountMap.put(word, wordCountMap.getOrDefault(word, 0) + 1);
}
}
} catch (Exception e) {
e.printStackTrace();//TODO 引入日志组件后用log.error替换
}
//转换成List去用sort的API,方便
// List<Map.Entry<String, Integer>> sortedWordList = new ArrayList<>(wordCountMap.entrySet());
// sortedWordList.sort(Comparator.comparing(Map.Entry::getValue).reversed());
// sortedWordList.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
//找TOP N
// for (int i = 0; i < n && i < sortedWordList.size(); i++) {
// topNWords.add(sortedWordList.get(i).getKey());
// }
PriorityQueue<Map.Entry<String, Integer>> maxHeap =
new PriorityQueue<>((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
for (Map.Entry<String, Integer> entry : wordCountMap.entrySet()) {
maxHeap.offer(entry);
}
if (!maxHeap.isEmpty()) {
for (int i = 0; i < n; i++) {
topNWords.add(maxHeap.poll().getKey());
}
}
return topNWords;
}
public static void main(String[] args) {
File inputFile = new File("D:/topn.txt");
int topN = 10;
List<String> topNWords = findTopNWords(inputFile, topN);
System.out.println("TopN搜索词列表:");
for (String word : topNWords) {
System.out.println(word);
}
}
}
云雨雪记不太清了,只记得百度一面确实是很标准的大厂面试,和我之前聊过的面试流程**5 年普通程序员的工作、面试与情感生活经历(八千字长文)**一样,八股居多,都算是比较进阶的八股,场景题问的不多。云雨雪的技术栈比较适配,印象中问了很多 elastic search 的问题,所幸都答上来了。百度面试会卡时间,一小时,云雨雪面的比较好,超时了。
比较令人惊喜的是一面过了,紧接着约了第二天晚上的二面。其实我觉得大中厂面试官普遍态度很好,据我所知面试是会给予一定奖励的,当然本身素质很高,云雨雪面试几乎没有遇到态度很差或者板着脸的。二面的时候印象中还是八股居多,问项目的情况变得更多了,很遗憾,这部分题也没有记录,但是记录了代码题,生产者消费者模型。
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ProducerConsumerExample {
public static void main(String[] args) {
// 创建共享的并发队列
Queue<Integer> queue = new ConcurrentLinkedQueue<>();
// Queue<Integer> queue = new LinkedBlockingQueue<>();
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1000));
AtomicInteger ai = new AtomicInteger(0);
// 提交生产者和消费者任务
for (int i = 0; i < 2; i++) {
executor.submit(new Producer(queue, ai));
}
for (int i = 0; i < 2; i++) {
executor.submit(new Consumer(queue));
}
// 关闭线程池
executor.shutdown();
}
// 生产者任务
static class Producer implements Runnable {
private final Queue<Integer> queue;
private final AtomicInteger value;
public Producer(Queue<Integer> queue, AtomicInteger value) {
this.value = value;
this.queue = queue;
}
@Override
public void run() {
while (true) {
// 生产新的数据并添加到队列
int val = value.incrementAndGet();
System.out.println("Produced: " + val);
queue.offer(val);
// 模拟生产耗时
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 消费者任务
static class Consumer implements Runnable {
private final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
// 从队列中取出数据并消费
Integer value = queue.poll();
if (value != null) {
System.out.println("Consumed: " + value);
}
// 模拟消费耗时
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
二面结束第二天,HR 跟云雨雪说不好意思 HC("Headcount" 的缩写,指的是公司或团队允许雇佣的员工人数)没了,很多和云雨雪一样在面试中的候选人只能拒了,事后确实了解到百度确实在裁员。云雨雪想进百度的意愿很强,因为当时女友在百度,如果有幸进去将会是一段佳话,哈哈。
最后回到正题,百度给云雨雪的体验是非常好的,很有技术感,问的很多问题都能感觉到面试官是真的在做技术,如流给我的印象也不错,可惜没进。
阿里一面
阿里没记错的话,云雨雪投的 JD 是来自于阿里健康,不是本部,文章末尾会介绍一下云雨雪的个人情况和工作项目经历,方便大家参考。忘了是用的什么会议软件了,应该是内部的,不是钉钉。自我介绍和项目介绍完毕后,面试官直接甩了套卷子...我当时就觉得凉了,因为根据我个人情况,凡是不想聊天直接让做题,多半是因为你的过往经历和技能没有能吸引到面试官的地方。当然说归说,题还是要做的,是给了一个 txt 文件,允许使用本地 IDE,我没有开 AI 编码,毕竟这样有点开挂嫌疑。
题目一共 5 道,两道代码题、一道场景设计和两道 SQL 题,没有评分,没有测试,共享做完面试官会收作业,反问环节结束面试就结束了。
代码题
System.out.println(Arrays.toString(bubbleSort(new int[]{64, 34, 25, 12, 22, 11, 90})));
private static int[] bubbleSort(int[] array) {
int n = array.length;
//避免越界
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
return array;
}
public static void main(String[] args) {
AtomicInteger ai = new AtomicInteger(1);
Semaphore a = new Semaphore(1);
Semaphore b = new Semaphore(0);
Semaphore c = new Semaphore(0);
try (ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100,
1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(100));) {
executor.submit(new Thread(() -> {
printNum(ai, a, b);
}));
executor.submit(new Thread(() -> {
printNum(ai, b, c);
}));
executor.submit(new Thread(() -> {
printNum(ai, c, a);
}));
}
}
private static void printNum(AtomicInteger ai, Semaphore cur, Semaphore next) {
while (ai.get() <= 100) {
try {
cur.acquire();
//必要--在多线程环境中,有可能一个线程已经通过了循环条件(ai.get() <= MAX_NUMBER)并且获取了信号量,而另一个线程(它已经在等待中)也通过了循环条件。如果没有额外的检查,两个线程可能在释放信号量之前都会打印超过上限的数字,导致输出不正确。
if (ai.get() <= 100) {
System.out.println(ai.getAndIncrement());
}
next.release();
} catch (InterruptedException e) {
throw new RuntimeException();
}
}
}
场景设计题
百万订单如何做分流策略,有几种,优劣势在哪?如何保证订单的幂等性?如何做重试策略以及告警策略?
云雨雪回答的不好,因为确实没有做过相关的业务,所以只能凭借经验回答,大致可以参考 下面 ChatGPT 的答案。
分流策略:
a. 基于订单 ID 的 Hash 分片:
- 优势:简单,每个订单都被分配到同一个处理节点。
- 劣势:如果订单分布不均匀,可能导致某些节点负载过重。
b. 基于订单属性的分片(如地理位置、订单类型等):
- 优势:能够根据订单属性实现更均匀的负载分布。
- 劣势:需要对订单属性进行分析,可能导致配置复杂。
c. 随机分片:
- 优势:简单,对于均匀分布的订单有效。
- 劣势:不适用于特定条件下需要有选择性的处理订单的情况。