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

静态代理:代理类在编译时就确定,需要手动编写代理类,与目标类实现相同的接口,在代理类中调用目标类的方法并添加额外逻辑。
动态代理:在运行时动态生成代理类,无需手动编写代理类代码。Java中主要通过java.lang.reflect.Proxy类实现,基于接口进行代理。
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项的值。
模型内容:OSI(开放系统互连)参考模型将网络通信分为七层,从下到上依次为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。实际中常用的是TCP/IP五层模型,将OSI的会话层、表示层和应用层合并为应用层。
各层作用
物理层:负责传输比特流,定义物理设备的标准,如网线的接口类型、光纤的接口类型、传输介质的传输速率等。
数据链路层:将物理层接收到的信号进行处理,封装成帧,负责帧的传输、差错检测和纠正等。
网络层:主要负责将数据包从源主机传输到目标主机,进行路由选择和分组转发。
传输层:提供端到端的可靠通信,确保数据的完整性和顺序性,常见的协议有TCP和UDP。
应用层:为用户的应用程序提供网络服务,如HTTP、FTP、SMTP等。
wifi所属层次:wifi属于数据链路层,它是一种无线局域网技术,用于在局部范围内实现设备的无线连接和数据传输。
ArrayList:基于动态数组实现,查询效率高,插入和删除效率较低(尤其是在数组中间插入或删除元素时,需要移动大量元素)。
LinkedList:基于双向链表实现,插入和删除效率高,查询效率较低(需要从头或尾节点开始遍历)。
Vector:与ArrayList类似,也是基于动态数组实现,但它是线程安全的,性能相对较低。
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的名称。例如:
堆内存泄漏:常见于对象被错误地引用,导致无法被垃圾回收。例如,在一个静态集合中添加了大量对象,但没有及时清理,这些对象会一直被静态集合引用,无法被回收。
栈内存泄漏:主要是在方法调用过程中,局部变量占用的栈空间无法及时释放。例如,在递归调用中,如果递归深度过大且没有正确的终止条件,可能会导致栈溢出。
方法区内存泄漏:方法区主要存储类的元数据、常量池等信息。如果程序中加载了大量的类,但没有及时卸载,可能会导致方法区内存泄漏。例如,在一个动态生成类的应用中,如果没有合理管理生成的类,可能会导致方法区内存占用过大。
最终一致性:指在分布式系统中,经过一段时间后,所有节点的数据最终会达到一致的状态,但在这段时间内,各个节点的数据可能不一致。
强一致性和最终一致性的例子
强一致性:例如,在关系型数据库中进行事务操作,当事务提交后,所有节点看到的数据都是一致的。
最终一致性:例如,在分布式缓存系统中,当数据更新时,不同节点的缓存可能不会立即同步,但经过一段时间后,所有节点的缓存数据会达到一致。
分布式事务和消息队列:分布式事务是指跨越多个节点或系统的事务操作,常见的解决方案有2PC(两阶段提交)、3PC(三阶段提交)、TCC(Try - Confirm - Cancel)、Saga模式等。消息队列可以用于解耦系统、异步处理、流量削峰等,在分布式事务中也可以作为实现最终一致性的手段之一。
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地址和端口,发起连接请求;服务端接受客户端的连接请求,建立连接。
通信过程:连接建立后,客户端和服务端可以通过输入输出流进行数据通信。客户端和服务端可以分别创建输入流和输出流,通过读写流来实现数据的发送和接收。
CPU优化:可以通过分析CPU使用率、线程状态等信息,找出CPU占用高的线程和代码段,进行优化,如减少不必要的计算、优化算法等。
IO优化:可以通过使用缓存、异步IO、批量处理等方式减少IO操作,提高系统性能。
内存优化:可以通过合理设置堆大小、优化对象创建和销毁、使用内存池等方式减少内存占用和内存碎片。
进程和线程:进程是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位;线程是进程中的一个执行单元,是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支持多种数据结构,如字符串(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等协议来解决。
单链表判环:使用快慢指针解决。快指针每次移动两步,慢指针每次移动一步,如果链表有环,快指针最终会追上慢指针;如果链表无环,快指针会先到达链表尾部。
完全二叉树判断:可以通过层序遍历的方式判断一棵二叉树是否为完全二叉树。在层序遍历过程中,如果遇到一个空节点,那么之后的所有节点都应该是空节点,否则就不是完全二叉树。
Docker原理:Docker基于Linux容器的技术,通过命名空间(Namespace)和控制组(Cgroup)实现资源的隔离和限制,将应用程序及其依赖打包成一个容器镜像,在运行时通过容器引擎加载镜像并运行容器。
Kubenetes原理:Kubenetes采用主从架构,包括Master节点和Node节点。Master节点负责集群的管理和控制,Node节点负责运行容器。Kubenetes通过一系列的控制器(如Deployment、ReplicaSet、Service等)来管理容器的部署、扩展和调度。
架构:Kubenetes的Master节点包括API Server、Scheduler、Controller Manager和etcd等组件;Node节点包括Kubelet、Kube - proxy和容器运行时等组件。
扩容方式:Kubenetes可以通过水平扩容(增加Pod的数量)和垂直扩容(增加Pod的资源限制)的方式来实现应用的扩容。水平扩容可以通过修改Deployment的副本数或使用Horizontal Pod Autoscaler(HPA)自动根据负载情况进行扩容。
强引用:是最常见的引用类型,只要强引用存在,垃圾回收器就不会回收被引用的对象。
软引用:用于描述一些还有用但并非必需的对象,在内存不足时,垃圾回收器会回收这些对象。
弱引用:比软引用更弱一些,被弱引用引用的对象只能生存到下一次垃圾回收之前,当垃圾回收器工作时,无论内存是否充足,都会回收被弱引用引用的对象。
虚引用:是最弱的一种引用类型,它不能单独使用,必须与引用队列(ReferenceQueue)联合使用,主要用于跟踪被垃圾回收器回收的活动。
找出1 - N + 1中未取的数:给定1 - N + 1这些数中取出N个,找出剩下的是哪个。不能使用简单的相减方法,可以采用排序后查找、使用哈希表统计数字出现次数等方法。
找出所有可能的IP地址组合:给定一串数字,找出所有可能的IP地址组合。例如,输入"192168111",输出["192.168.1.11", "192.168.11.1"]。可以通过回溯算法来解决这个问题,尝试在不同的位置插入点号,生成所有可能的IP地址组合,然后判断这些组合是否合法。