百度研发面经整合版

百度研发面经整合版
最新回答
许多

2026-10-21 19:59:53

百度研发面经整合版

本文整合了百度不同部门(百度智能云账号和消息部门、百度核心搜索部、百度智能云基础研发工程师)的研发岗位面试经验,涵盖多轮面试的技术问题与非技术问题,为准备百度研发岗位面试的候选人提供参考。

百度智能云账号和消息部门

一面
  • 项目:深入探讨过往项目经历,包括项目背景、目标、所采用的技术栈、遇到的问题及解决方案等。
  • AOP:解释面向切面编程的概念,包括切面、连接点、切入点、通知等核心概念,以及AOP在实际项目中的应用场景和优势。
  • 动态代理和静态代理的区别

    静态代理:代理类在编译时就确定,需要手动编写代理类,与目标类实现相同的接口,在代理类中调用目标类的方法并添加额外逻辑。

    动态代理:在运行时动态生成代理类,无需手动编写代理类代码。Java中主要通过java.lang.reflect.Proxy类实现,基于接口进行代理。

  • TCP和IP报文分片情况

    TCP分片:TCP协议本身不会对数据进行分片,但当应用层数据过大时,TCP会将数据拆分成多个段(Segment),每个段有自己的序列号和确认号等信息。当TCP段的大小超过网络的MTU(最大传输单元)时,IP层会对TCP段进行分片。

    IP分片:当IP数据包的大小超过网络的MTU时,IP层会将数据包分片成多个较小的数据包,每个分片都有自己的IP头部,其中包含标识符、分片偏移量和标志位等信息,以便接收方能够重新组装数据包。

    TCP分包后是否还会进行IP分片:会的。TCP分包后得到的TCP段如果仍然超过网络的MTU,IP层会对其进行分片。

  • 算法题

    无限长轨道两车相遇问题:两辆车同方向开且会滴水,可通过让两车以特定方式滴水,根据水滴的位置或时间来判断它们是否相遇。例如,让一辆车每隔固定时间滴一滴水,另一辆车在接收到水滴信号后改变滴水频率或方式,通过观察水滴的变化来确定相遇。

    斐波那契数列

    递归式及改进:递归实现斐波那契数列简单直观,但存在大量重复计算,时间复杂度为O(2^n)。可以使用备忘录模式(Memoization)来存储已经计算过的结果,避免重复计算,将时间复杂度降低到O(n)。

    dp方式及优化空间:使用动态规划(dp)可以自底向上计算斐波那契数列,时间复杂度为O(n),空间复杂度为O(n)(使用数组存储中间结果)。为了优化空间,可以用三个变量代替数组进行dp,将空间复杂度降低到O(1)。

    数学公式:斐波那契数列的通项公式为$F(n)=frac{1}{sqrt{5}}[(frac{1 + sqrt{5}}{2})^n-(frac{1 - sqrt{5}}{2})^n]$,可以直接通过公式计算第n项的值。

  • Linux内存结构与JVM内存映射:Linux内存结构包括用户空间和内核空间,用户空间又分为堆、栈、代码段、数据段等。JVM内存结构包括堆、栈、方法区、程序计数器等。两者之间的映射关系较为复杂,JVM的堆和方法区通常在用户空间的堆中分配内存,JVM的栈与Linux的栈有一定的对应关系,但具体实现因操作系统和JVM版本而异。
二面
  • 项目:进一步深入讨论项目细节,包括项目的架构设计、性能优化、遇到的挑战及解决方案等,可能会针对项目的某些关键部分进行详细追问。
  • 排序算法及复杂度:介绍常见排序算法(如冒泡排序、插入排序、选择排序、快速排序、归并排序等)的原理、时间复杂度和空间复杂度。快速排序的平均时间复杂度为O(nlogn),最坏情况下为O(n^2),空间复杂度为O(logn)(递归调用栈的空间)。
  • OSI七层模型

    模型内容:OSI(开放系统互连)参考模型将网络通信分为七层,从下到上依次为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。实际中常用的是TCP/IP五层模型,将OSI的会话层、表示层和应用层合并为应用层。

    各层作用

    物理层:负责传输比特流,定义物理设备的标准,如网线的接口类型、光纤的接口类型、传输介质的传输速率等。

    数据链路层:将物理层接收到的信号进行处理,封装成帧,负责帧的传输、差错检测和纠正等。

    网络层:主要负责将数据包从源主机传输到目标主机,进行路由选择和分组转发。

    传输层:提供端到端的可靠通信,确保数据的完整性和顺序性,常见的协议有TCP和UDP。

    应用层:为用户的应用程序提供网络服务,如HTTP、FTP、SMTP等。

    wifi所属层次:wifi属于数据链路层,它是一种无线局域网技术,用于在局部范围内实现设备的无线连接和数据传输。

  • 线程间同步方式:在Java中,线程间同步可以使用object类的方法,如wait()、notify()和notifyAll(),这些方法用于在同步块中实现线程的等待和唤醒机制。此外,还可以使用synchronized关键字、Lock接口及其实现类(如ReentrantLock)等进行线程同步。
  • HashMap重写方法及场景:使用HashMap时,如果存储的对象是自定义类,通常需要重写hashCode()和equals()方法。重写hashCode()方法是为了确保相同的对象在HashMap中能够被分配到相同的桶(bucket)中,重写equals()方法是为了在发生哈希冲突时能够正确判断两个对象是否相等。例如,在一个学生管理系统中,使用HashMap存储学生对象,以学生ID作为键,需要根据学生ID来判断两个学生对象是否相同,此时就需要重写Student类的hashCode()和equals()方法。
  • 常用数据结构及List区别:常用的数据结构有数组、链表、栈、队列、树、图等。在Java中,List接口有三个主要的实现类:ArrayList、LinkedList和Vector。

    ArrayList:基于动态数组实现,查询效率高,插入和删除效率较低(尤其是在数组中间插入或删除元素时,需要移动大量元素)。

    LinkedList:基于双向链表实现,插入和删除效率高,查询效率较低(需要从头或尾节点开始遍历)。

    Vector:与ArrayList类似,也是基于动态数组实现,但它是线程安全的,性能相对较低。

  • Spring中的IOC和AOP

    IOC(控制反转):将对象的创建、管理和依赖关系注入等工作交给Spring容器来完成,降低了对象之间的耦合度。常见的IOC注解有@Component、@Service、@Repository、@Controller、@Autowired、@Resource等。

    AOP(面向切面编程):将与业务逻辑无关的横切关注点(如日志、事务、安全等)从业务逻辑中分离出来,通过动态代理的方式在运行时将这些横切关注点织入到业务逻辑中。

    @Autowired和@Resource的区别

    @Autowired:是Spring提供的注解,默认按类型进行自动装配,如果存在多个相同类型的bean,可以结合@Qualifier注解指定bean的名称进行装配。

    @Resource:是JSR - 250提供的注解,默认按名称进行自动装配,如果名称不存在,则按类型进行装配。

    作用域:Spring中bean的作用域有singleton(单例,默认)、prototype(原型)、request(请求)、session(会话)、application(应用程序)等。

    @Autowired配置两个类中的一个:可以使用@Qualifier注解指定要装配的bean的名称。例如:

@Component("classA")public class ClassA {}@Component("classB")public class ClassB {}@Servicepublic class MyService { @Autowired @Qualifier("classA") private ClassA classA;}
  • 单例模式:单例模式确保一个类只有一个实例,并提供一个全局访问点。常见的实现方式有饿汉式、懒汉式、双重检测锁模式等。双重检测锁模式的实现代码如下:
public class Singleton { private static volatile Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }}
  • Java内存泄漏及产生情况:Java中的内存泄漏是指程序中已分配的内存无法被垃圾回收器回收,导致内存占用不断增加。Java的堆、栈和方法区都可能产生内存泄漏。

    堆内存泄漏:常见于对象被错误地引用,导致无法被垃圾回收。例如,在一个静态集合中添加了大量对象,但没有及时清理,这些对象会一直被静态集合引用,无法被回收。

    栈内存泄漏:主要是在方法调用过程中,局部变量占用的栈空间无法及时释放。例如,在递归调用中,如果递归深度过大且没有正确的终止条件,可能会导致栈溢出。

    方法区内存泄漏:方法区主要存储类的元数据、常量池等信息。如果程序中加载了大量的类,但没有及时卸载,可能会导致方法区内存泄漏。例如,在一个动态生成类的应用中,如果没有合理管理生成的类,可能会导致方法区内存占用过大。

三面
  • 主要了解的技术:介绍自己熟悉的技术领域,如编程语言、框架、数据库、网络等。
  • 分布式系统设计:分布式系统设计需要考虑CAP(一致性、可用性、分区容错性)和BASE(基本可用、软状态、最终一致性)理论,最终一致性是分布式系统中的一种常见一致性模型。

    最终一致性:指在分布式系统中,经过一段时间后,所有节点的数据最终会达到一致的状态,但在这段时间内,各个节点的数据可能不一致。

    强一致性和最终一致性的例子

    强一致性:例如,在关系型数据库中进行事务操作,当事务提交后,所有节点看到的数据都是一致的。

    最终一致性:例如,在分布式缓存系统中,当数据更新时,不同节点的缓存可能不会立即同步,但经过一段时间后,所有节点的缓存数据会达到一致。

    分布式事务和消息队列:分布式事务是指跨越多个节点或系统的事务操作,常见的解决方案有2PC(两阶段提交)、3PC(三阶段提交)、TCC(Try - Confirm - Cancel)、Saga模式等。消息队列可以用于解耦系统、异步处理、流量削峰等,在分布式事务中也可以作为实现最终一致性的手段之一。

  • 分布式事务的消息ID确认顺序:可以使用ZooKeeper(zk)来确认消息的顺序。ZooKeeper是一个分布式协调服务,可以提供分布式锁、顺序节点等功能,通过创建顺序节点来保证消息的顺序性。
  • zk性能瓶颈及克服方法:ZooKeeper在处理大量并发请求时可能会出现性能瓶颈,可以使用Redis和Redis集群来提高性能。Redis是一个高性能的内存数据库,可以作为缓存层来减轻ZooKeeper的负担。
  • 跨机房网络延迟及解决:跨机房的网络延迟会受到多种因素的影响,如距离、网络带宽、网络拥塞等。华北到华南的网络延迟时间大概在几十毫秒到几百毫秒之间,具体时间取决于网络状况。解决跨机房网络延迟的方法有优化网络架构、使用CDN加速、采用异地多活架构等。
  • 网络编程

    Socket编程:Socket是网络编程中的基本概念,是应用程序与网络之间的接口。在Java中,可以使用java.net.Socket和java.net.ServerSocket类来实现客户端和服务端的通信。

    NIO和BIO区别

    BIO(Blocking I/O):同步阻塞式I/O,在读写数据时,线程会一直阻塞,直到数据读写完成。

    NIO(Non - blocking I/O):同步非阻塞式I/O,采用事件驱动机制,线程在读写数据时不会一直阻塞,可以通过选择器(Selector)来监听多个通道(Channel)的事件,实现多路复用。

    阻塞的含义:在BIO中,阻塞指的是当线程调用读写方法时,如果数据没有准备好或没有可用的空间,线程会一直等待,直到数据准备好或有可用空间为止。

    Socket客户端和服务端的连接过程和通信过程

    连接过程:服务端创建ServerSocket并绑定端口,然后监听客户端的连接请求;客户端创建Socket并指定服务端的IP地址和端口,发起连接请求;服务端接受客户端的连接请求,建立连接。

    通信过程:连接建立后,客户端和服务端可以通过输入输出流进行数据通信。客户端和服务端可以分别创建输入流和输出流,通过读写流来实现数据的发送和接收。

  • 操作系统、Shell和命令:了解操作系统的基本概念、进程管理、内存管理、文件系统等知识,熟悉常用的shell命令和操作。
  • 算法熟悉程度:介绍自己对算法的掌握程度,包括常见算法的原理、实现和应用。
  • 系统设计及设计模式应用:系统设计需要考虑系统的架构、模块划分、接口设计、数据存储等方面。设计模式是解决特定问题的经验总结,在系统设计中可以根据具体需求选择合适的设计模式,如单例模式、工厂模式、观察者模式等。
  • 系统优化及问题排查:系统优化可以从CPU、IO、内存等方面入手。

    CPU优化:可以通过分析CPU使用率、线程状态等信息,找出CPU占用高的线程和代码段,进行优化,如减少不必要的计算、优化算法等。

    IO优化:可以通过使用缓存、异步IO、批量处理等方式减少IO操作,提高系统性能。

    内存优化:可以通过合理设置堆大小、优化对象创建和销毁、使用内存池等方式减少内存占用和内存碎片。

  • 个人情况:了解候选人的家乡、女朋友等情况,主要是为了营造轻松的面试氛围,了解候选人的生活背景。

百度核心搜索部

一面
  • 自我介绍:简要介绍自己的教育背景、项目经历、技术技能和个人优势等。
  • Docker和k8s了解程度:Docker是一个开源的应用容器引擎,可以将应用程序及其依赖打包成一个容器,实现应用程序的快速部署和运行。k8s(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。了解它们的基本概念、架构、常用命令和操作等。
  • 研究生课程:介绍研究生阶段学习的主要课程,如算法设计与分析、数据库系统、分布式系统、计算机网络等,以及这些课程对自己技术能力的提升。
  • 操作系统

    进程和线程:进程是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位;线程是进程中的一个执行单元,是CPU调度和分派的基本单位。一个进程可以包含多个线程,线程共享进程的资源。

    死锁和处理方式:死锁是指两个或多个进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,这些进程都将无法继续执行下去。常见的死锁处理方式有预防死锁、避免死锁、检测死锁和解除死锁等。

  • 内存管理

    虚拟内存:虚拟内存是一种内存管理技术,它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。

    页面置换:当虚拟内存中的页面需要访问时,如果该页面不在物理内存中,就会发生缺页中断,操作系统需要将该页面从磁盘调入物理内存。如果物理内存已满,就需要选择一个页面进行置换,常见的页面置换算法有先进先出(FIFO)、最近最少使用(LRU)、时钟(Clock)等。

  • 网络

    三次握手和四次挥手

    三次握手:用于建立TCP连接。客户端向服务端发送SYN包,请求建立连接;服务端收到SYN包后,回复SYN + ACK包,表示同意建立连接;客户端收到SYN + ACK包后,回复ACK包,连接建立成功。

    四次挥手:用于释放TCP连接。客户端向服务端发送FIN包,请求释放连接;服务端收到FIN包后,回复ACK包,表示收到释放请求;服务端处理完数据后,向客户端发送FIN包,请求释放连接;客户端收到FIN包后,回复ACK包,连接释放成功。

  • 数据库

    MySQL索引:索引是提高数据库查询性能的重要手段,它可以加快数据的检索速度。常见的索引类型有普通索引、唯一索引、主键索引、复合索引等。

    事务:事务是一组原子性的SQL查询,或者是一个独立的工作单元。事务具有ACID(原子性、一致性、隔离性、持久性)特性。

    锁:数据库中的锁用于控制并发访问,保证数据的一致性和完整性。常见的锁类型有共享锁(S锁)、排他锁(X锁)、意向锁等。

  • Redis

    数据结构:Redis支持多种数据结构,如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。

    持久化方式:Redis提供了两种持久化方式,即RDB(Redis Database)和AOF(Append - Only File)。RDB是通过定期将内存中的数据快照保存到磁盘上;AOF是通过记录所有写操作命令,在服务器重启时重新执行这些命令来恢复数据。

    使用场景:Redis可以用于缓存、消息队列、分布式锁等场景。

  • 分布式系统

    负载均衡方式:常见的负载均衡方式有DNS负载均衡、Nginx负载均衡、LVS负载均衡和硬件负载均衡等。

    一致性问题解决方案:分布式系统中的一致性问题可以通过2PC、3PC、Raft、Paxos、Zab等协议来解决。

  • MySQL大表数据查询优化:对于MySQL大表数据查询,可以采用分表、分库的方式进行优化。分表是将一个大表按照一定的规则拆分成多个小表,分库是将数据分散到不同的数据库中,减少单个表或数据库的数据量,提高查询性能。
  • 算法题

    单链表判环:使用快慢指针解决。快指针每次移动两步,慢指针每次移动一步,如果链表有环,快指针最终会追上慢指针;如果链表无环,快指针会先到达链表尾部。

    完全二叉树判断:可以通过层序遍历的方式判断一棵二叉树是否为完全二叉树。在层序遍历过程中,如果遇到一个空节点,那么之后的所有节点都应该是空节点,否则就不是完全二叉树。

二面
  • 项目:深入讨论项目的技术细节、架构设计、性能优化、遇到的问题及解决方案等,可能会要求候选人进行代码演示或系统演示。
  • Docker和kubenetes原理及了解程度

    Docker原理:Docker基于Linux容器的技术,通过命名空间(Namespace)和控制组(Cgroup)实现资源的隔离和限制,将应用程序及其依赖打包成一个容器镜像,在运行时通过容器引擎加载镜像并运行容器。

    Kubenetes原理:Kubenetes采用主从架构,包括Master节点和Node节点。Master节点负责集群的管理和控制,Node节点负责运行容器。Kubenetes通过一系列的控制器(如Deployment、ReplicaSet、Service等)来管理容器的部署、扩展和调度。

  • Docker的cgroup了解程度:Cgroup(Control Groups)是Linux内核的一个功能,用于限制、记录和隔离进程组的资源使用(如CPU、内存、磁盘I/O等)。Docker使用Cgroup来实现对容器资源的控制和管理。
  • Kubenetes的架构及扩容方式

    架构:Kubenetes的Master节点包括API Server、Scheduler、Controller Manager和etcd等组件;Node节点包括Kubelet、Kube - proxy和容器运行时等组件。

    扩容方式:Kubenetes可以通过水平扩容(增加Pod的数量)和垂直扩容(增加Pod的资源限制)的方式来实现应用的扩容。水平扩容可以通过修改Deployment的副本数或使用Horizontal Pod Autoscaler(HPA)自动根据负载情况进行扩容。

  • Java的四种引用:Java中有四种引用类型,即强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)。

    强引用:是最常见的引用类型,只要强引用存在,垃圾回收器就不会回收被引用的对象。

    软引用:用于描述一些还有用但并非必需的对象,在内存不足时,垃圾回收器会回收这些对象。

    弱引用:比软引用更弱一些,被弱引用引用的对象只能生存到下一次垃圾回收之前,当垃圾回收器工作时,无论内存是否充足,都会回收被弱引用引用的对象。

    虚引用:是最弱的一种引用类型,它不能单独使用,必须与引用队列(ReferenceQueue)联合使用,主要用于跟踪被垃圾回收器回收的活动。

  • Java的线程通信方式:Java中线程间通信可以使用wait()、notify()和notifyAll()方法,这些方法必须在同步块或同步方法中使用。此外,还可以使用BlockingQueue、Condition等类实现线程间通信。
  • Linux的进程通信方式:Linux中进程间通信的方式有管道(Pipe)、命名管道(FIFO)、消息队列(Message Queue)、共享内存(Shared Memory)、信号量(Semaphore)和套接字(Socket)等。
  • Java的线程池:Java中的线程池可以通过Executors类提供的工厂方法来创建,常见的线程池类型有FixedThreadPool、CachedThreadPool、ScheduledThreadPool等。线程池可以有效地管理线程资源,提高系统的性能和稳定性。
  • 算法题

    找出1 - N + 1中未取的数:给定1 - N + 1这些数中取出N个,找出剩下的是哪个。不能使用简单的相减方法,可以采用排序后查找、使用哈希表统计数字出现次数等方法。

    找出所有可能的IP地址组合:给定一串数字,找出所有可能的IP地址组合。例如,输入"192168111",输出["192.168.1.11", "192.168.11.1"]。可以通过回溯算法来解决这个问题,尝试在不同的位置插入点号,生成所有可能的IP地址组合,然后判断这些组合是否合法。

三面
  • 项目:进一步深入讨论项目的创新点、对业务的推动作用、项目的可持续性等,评估候选人的项目能力和业务理解能力。
  • 家庭情况:了解候选人的家庭背景、家庭支持情况等,主要是为了了解候选人的生活稳定性和