字节后端面试面经综合分析

目录

一、字节豆包后端一面面经解析

(一)自我介绍

(二)实习项目拷打

(三)手撕代码

(四)C++ 多态相关问题

(五)智能指针相关问题

(六)malloc 相关问题

(七)mmap 相关问题

(八)多线程相关问题

(九)MySQL 存储引擎相关问题

(十)Redis 持久化相关问题

(十一)前沿知识相关问题

(十二)反问环节

二、字节广告后端一面面经解析

(一)自我介绍

(二)实习项目拷打

(三)文件系统相关问题

(四)Linux IO 多路复用相关问题

(五)进程和线程相关问题

(六)创建子进程相关问题

(七)Python 代码分析问题

(八)手撕代码

(九)TCP 相关问题

(十)反问环节

三、字节广告后端二面面经解析

(一)自我介绍

(二)项目拷打

(三)编程语言相关问题

(四)C++ 相关问题

(五)系统设计问题

(六)性能问题

(七)手撕代码

(八)反问环节

四、总结


一、字节豆包后端一面面经解析

(一)自我介绍

简要介绍自己的教育背景、项目经验和技能特长。

(二)实习项目拷打

详细介绍实习项目的背景、目标、技术架构、实现过程以及遇到的问题和解决方案。

(三)手撕代码

  1. 手撕:lc206 链表反转
    • 思路:使用三个指针,分别指向当前节点、前一个节点和下一个节点。遍历链表,将当前节点的 next 指针指向前一个节点,然后移动三个指针到下一个位置,直到遍历完整个链表。
    • 代码示例(Java):

class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;
    ListNode next = null;
    while (curr!= null) {
        next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}

  1. 手撕:lc70 爬楼梯进阶,爬楼梯高级进阶:一次可以跳 1 - n 阶台阶
    • 思路:这是一个动态规划问题。定义 dp[i] 表示爬到第 i 阶楼梯的方法数。对于第 i 阶楼梯,可以从第 i - 1i - 2、...、i - n 阶楼梯跳上来,所以 dp[i] = dp[i - 1] + dp[i - 2] +... + dp[i - n]。初始条件为 dp[0] = 1dp[1] = 1,...,dp[n - 1] = 2^(n - 1)
    • 代码示例(Java):

public class ClimbingStairsAdvanced {
    public int climbStairs(int n) {
        if (n <= 2) return n;
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= Math.min(i, 3); j++) {
                dp[i] += dp[i - j];
            }
        }
        return dp[n];
    }
}

(四)C++ 多态相关问题

  1. C++ 的多态实现原理是什么?
    • 答案:C++ 多态主要通过虚函数实现。在基类中声明虚函数,在派生类中重写虚函数,通过基类指针或引用调用虚函数时,根据实际对象的类型决定调用哪个函数。虚函数的实现是通过在类中添加一个虚函数表,每个包含虚函数的类都有一个虚函数表,其中存储了该类的虚函数地址。对象的首地址通常存储着一个指向虚函数表的指针。
  2. 多态分几种类型?
    • 答案:C++ 多态主要分为静态多态和动态多态。静态多态通过函数重载和模板实现,在编译期确定调用的函数。动态多态通过虚函数实现,在运行期根据对象的实际类型确定调用的函数。
  3. 多态的特点有哪些?
    • 答案:多态的特点包括提高代码的可扩展性和可维护性、实现代码的复用、增强程序的灵活性等。通过多态,可以在不修改原有代码的情况下,增加新的功能和行为。

(五)智能指针相关问题

  1. 智能指针本质是什么?
    • 答案:智能指针是一种类,它通过封装原始指针,实现了自动的内存管理。智能指针的本质是通过引用计数或所有权转移等机制,确保在适当的时候释放所指向的资源,避免内存泄漏和悬空指针等问题。

(六)malloc 相关问题

  1. malloc 是如何工作的?底层调度原理,是系统调用吗?
    • 答案:malloc 是 C 语言中的动态内存分配函数。它通过向操作系统请求一块连续的内存空间来满足用户的需求。底层调度原理通常是通过系统调用(如 brk 或 mmap)来实现的。在一些实现中,malloc 可能会使用一些优化策略,如内存池、缓存等,以提高内存分配的效率。
  2. malloc 有哪些缺点?
    • 答案:malloc 的缺点包括可能会产生内存碎片、不支持对象的自动析构、容易出现内存泄漏等问题。此外,malloc 的性能可能会受到系统调用的开销和内存分配策略的影响。

(七)mmap 相关问题

  1. mmap 是什么?
    • 答案:mmap(Memory Mapping)是一种内存映射文件的方法。它将文件或设备的一部分映射到进程的地址空间中,使得进程可以像访问内存一样访问文件或设备。mmap 可以提高文件访问的效率,减少内存拷贝的次数。

(八)多线程相关问题

  1. 多线程会有什么问题?
    • 答案:多线程可能会带来一些问题,如线程安全问题(数据竞争、死锁等)、线程切换的开销、资源竞争等。此外,多线程的调试和错误处理也比较复杂。

(九)MySQL 存储引擎相关问题

  1. Mysql 的存储引擎你知道那些?区别是什么?

    • 答案:MySQL 常见的存储引擎有 InnoDB、MyISAM、Memory 等。
    • InnoDB:支持事务、行级锁、外键约束,具有较好的并发性能和数据完整性。
    • MyISAM:不支持事务和行级锁,但查询速度较快,适合读多写少的场景。
    • Memory:将数据存储在内存中,速度非常快,但数据在服务器重启后会丢失。
  2. 索引分别有什么结构?

    • 答案:MySQL 索引主要有 B + 树索引和哈希索引。B + 树索引是最常见的索引结构,它具有高效的范围查询和排序性能。哈希索引适用于等值查询,但不支持范围查询和排序。
  3. B + 树和 B 树有什么区别?

    • 答案:B + 树和 B 树都是平衡树数据结构,用于索引数据。它们的主要区别包括:
      • B + 树的非叶子节点只存储键值信息,不存储数据,所有数据都存储在叶子节点中。B 树的非叶子节点和叶子节点都存储数据。
      • B + 树的叶子节点之间通过指针连接,形成一个有序链表,方便范围查询和排序。B 树的叶子节点之间没有连接。
      • B + 树的高度通常比 B 树低,因此查询效率更高。
  4. 索引使用的时候有什么需要注意的?

    • 答案:使用索引时需要注意以下几点:
      • 选择合适的列创建索引,避免在频繁更新的列上创建索引。
      • 索引不是越多越好,过多的索引会增加存储开销和维护成本。
      • 避免在查询条件中使用函数或表达式,这可能会导致索引失效。
      • 对于大表,创建索引可能会消耗大量的时间和空间,需要谨慎考虑。
  5. 索引的缺点是什么?

    • 答案:索引的缺点包括占用额外的存储空间、增加数据插入、更新和删除的时间开销、可能导致查询优化器选择错误的执行计划等。
  6. 使用索引查询一定会变快么?

    • 答案:使用索引查询不一定会变快。如果查询条件不满足索引的使用条件,或者查询结果集非常大,索引可能无法提高查询性能。此外,如果索引的维护成本过高,也可能导致查询性能下降。

(十)Redis 持久化相关问题

  1. redis 有哪些持久化策略?二者在实际使用上有什么差异呢?
    • 答案:Redis 有两种持久化策略:RDB(Redis Database)和 AOF(Append Only File)。
    • RDB:是一种快照式的持久化方式,将 Redis 数据库在某个时间点的数据快照保存到磁盘上。RDB 持久化的优点是恢复速度快,适合用于数据备份和灾难恢复。缺点是可能会丢失数据,因为只有在特定的时间点进行快照。
    • AOF:是一种日志式的持久化方式,将 Redis 执行的所有写命令记录到一个日志文件中。AOF 持久化的优点是可以保证数据的完整性,因为所有的写命令都被记录下来了。缺点是文件体积较大,恢复时间较长。

(十一)前沿知识相关问题

  1. 最近学习了那些前沿知识?
    • 答案:可以介绍自己最近学习的前沿技术,如人工智能、大数据、区块链、容器化技术、云原生等。同时,可以分享自己对这些技术的理解和应用场景的思考。

(十二)反问环节

可以询问关于岗位的具体工作内容、团队技术栈、发展机会等问题。

二、字节广告后端一面面经解析

(一)自我介绍

简要介绍自己的教育背景、项目经验和技能特长。

(二)实习项目拷打

详细介绍实习项目的背景、目标、技术架构、实现过程以及遇到的问题和解决方案。

(三)文件系统相关问题

  1. 描述一下我们打开一个文件到读数据,操作系统是如何定位到文件的?

    • 答案:操作系统通过文件系统来定位文件。当打开一个文件时,操作系统会根据文件路径查找文件所在的目录结构。目录结构通常是一棵树,每个节点代表一个目录或文件。操作系统会从根目录开始,根据文件路径中的目录名逐步向下查找,直到找到目标文件。在找到文件后,操作系统会获取文件的元数据,包括文件的位置、大小、权限等信息。然后,操作系统可以根据这些信息来读取文件的数据。
  2. 文件的逻辑结构是什么?

    • 答案:文件的逻辑结构是指从用户的角度看到的文件的组织形式。常见的文件逻辑结构有顺序文件、索引文件和索引顺序文件。
    • 顺序文件:文件中的数据按照顺序存储,只能按照顺序访问。
    • 索引文件:文件由数据文件和索引表组成。索引表记录了数据文件中每个记录的位置信息,可以通过索引表快速访问文件中的任意记录。
    • 索引顺序文件:在顺序文件的基础上,增加了索引表,以提高文件的随机访问性能。

(四)Linux IO 多路复用相关问题

  1. Linux 里的 IO 多路复用有哪些?

    • 答案:Linux 中的 IO 多路复用机制有 select、poll 和 epoll。
    • select:通过遍历文件描述符集合来检查是否有事件发生。它的缺点是文件描述符数量有限,并且每次调用都需要遍历整个集合,效率较低。
    • poll:与 select 类似,但没有文件描述符数量的限制。
    • epoll:是一种高效的 IO 多路复用机制,它通过事件通知的方式来避免遍历文件描述符集合。epoll 可以同时支持大量的文件描述符,并且在有事件发生时,只通知发生事件的文件描述符,提高了效率。
  2. epoll 中的两个模式有什么区别?什么场景下如何选择?

    • 答案:epoll 有两种工作模式:水平触发(LT)和边缘触发(ET)。
    • 水平触发:只要文件描述符上有可读或可写事件,就会一直触发通知。这种模式适用于处理大量的连接,并且每次只读取或写入一部分数据的情况。
    • 边缘触发:只有在文件描述符状态从不可读 / 不可写变为可读 / 可写时,才会触发通知。这种模式适用于处理少量的连接,并且每次需要尽可能多地读取或写入数据的情况。

(五)进程和线程相关问题

  1. 进程和线程的区别?
    • 答案:进程和线程的区别主要包括以下几个方面:
      • 定义:进程是操作系统进行资源分配和调度的基本单位,拥有独立的内存空间和系统资源。线程是进程中的一个执行单元,共享进程的内存空间和系统资源。
      • 开销:创建和切换进程的开销比创建和切换线程的开销大,因为进程需要分配独立的内存空间和系统资源,而线程只需要在进程的内存空间中进行切换。
      • 通信方式:进程间通信相对复杂,需要使用管道、消息队列、共享内存等方式。线程间通信相对简单,可以直接访问共享的内存空间。
      • 并发性:多个进程可以在不同的处理器上同时运行,实现真正的并行。多个线程在同一进程中可以在不同的处理器上同时运行,但由于共享内存空间,可能会出现竞争条件和死锁等问题。

(六)创建子进程相关问题

  1. Linux 环境下如何创建子进程?fork ()?
    • 答案:在 Linux 环境下,可以使用 fork () 系统调用创建子进程。fork () 函数会创建一个新的进程,新进程是原进程的副本,包括代码、数据和打开的文件描述符等。fork () 函数返回两次,在父进程中返回子进程的进程 ID,在子进程中返回 0。

(七)Python 代码分析问题

  1. 一个 python 代码,解释一下输出结果。
    • 分析给定的 Python 代码,解释代码的执行过程和输出结果。根据代码的具体逻辑进行分析,包括文件操作、多进程等方面的内容。

(八)手撕代码

  1. 最小操作次数:给定一个数组,和一个目标值 x,每次可以从数字最左边或最右边的元素删除一个数字,将 x 减去删去的这个数字,如果 x 可以减为 0,则返回最少操作次数,否则返回 -1。数字都是非负整数,说一下时空复杂度。
    • 思路:可以使用动态规划的思想来解决这个问题。定义 dp[i][j]表示使用前 i个数字,将目标值减为 j所需的最少操作次数。对于 dp[i][j],可以从 dp[i - 1][j](不使用第 i个数字)和 dp[i - 1][j - nums[i - 1]](使用第 i个数字)中选择较小的值加一。如果 j < nums[i - 1],则只能从 dp[i - 1][j]中选择。初始条件为 dp[0][0] = 0,其他 dp[0][j] = -1
    • 代码示例(Python):

def min_operations(nums, x):
    n = len(nums)
    dp = [[-1] * (x + 1) for _ in range(n + 1)]
    dp[0][0] = 0
    for i in range(1, n + 1):
        for j in range(x + 1):
            if j < nums[i - 1]:
                dp[i][j] = dp[i - 1][j]
            else:
                if dp[i - 1][j]!= -1 and dp[i - 1][j - nums[i - 1]]!= -1:
                    dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - nums[i - 1]] + 1)
                elif dp[i - 1][j - nums[i - 1]]!= -1:
                    dp[i][j] = dp[i - 1][j - nums[i - 1]] + 1
                else:
                    dp[i][j] = dp[i - 1][j]
    return dp[n][x]

(九)TCP 相关问题

  1. 说一下 TCP 的三次握手和四次挥手?

    • 答案:TCP 的三次握手过程如下:
      • 第一次握手:客户端向服务器发送一个 SYN 报文,请求建立连接。
      • 第二次握手:服务器收到 SYN 报文后,向客户端发送一个 SYN/ACK 报文,确认收到客户端的请求,并请求建立连接。
      • 第三次握手:客户端收到 SYN/ACK 报文后,向服务器发送一个 ACK 报文,确认收到服务器的请求,建立连接。
    • TCP 的四次挥手过程如下:
      • 第一次挥手:客户端向服务器发送一个 FIN 报文,请求关闭连接。
      • 第二次挥手:服务器收到 FIN 报文后,向客户端发送一个 ACK 报文,确认收到客户端的请求。
      • 第三次挥手:服务器向客户端发送一个 FIN 报文,请求关闭连接。
      • 第四次挥手:客户端收到 FIN 报文后,向服务器发送一个 ACK 报文,确认收到服务器的请求,关闭连接。
  2. 为什么不能是三次挥手?

    • 答案:在 TCP 连接中,当客户端发送 FIN 报文请求关闭连接时,服务器可能还有数据要发送给客户端,所以不能立即关闭连接。服务器需要先发送 ACK 报文确认收到客户端的请求,然后继续发送数据。当服务器发送完数据后,再发送 FIN 报文请求关闭连接。客户端收到 FIN 报文后,发送 ACK 报文确认收到服务器的请求,关闭连接。所以需要四次挥手。
  3. TCP 的重发机制是什么?
    • 答案:TCP 的重发机制是通过定时器实现的。当发送方发送一个数据段后,会启动一个定时器。如果在定时器超时之前没有收到接收方的确认应答(ACK),发送方就会认为这个数据段丢失了,然后重新发送这个数据段。

    • TCP 的重发机制还包括快速重传和拥塞控制。当接收方连续收到三个相同的 ACK 时,就会认为这个数据段丢失了,然后立即重传这个数据段,这就是快速重传。拥塞控制是为了避免网络拥塞,当网络拥塞时,发送方会减少发送数据的速度,以避免更多的数据丢失。

(十)反问环节

可以询问关于岗位的具体工作内容、团队技术栈、发展机会等问题。

三、字节广告后端二面面经解析

(一)自我介绍

简要介绍自己的教育背景、项目经验和技能特长。

(二)项目拷打

详细探讨之前在字节和广告业务合作的项目,包括项目的背景、目标、技术架构、实现过程以及遇到的问题和解决方案。

(三)编程语言相关问题

  1. 平时开发用什么语言?
    • 答案:根据自己的实际情况回答,如 Java、Python、C++ 等,并简要介绍在使用该语言时的一些经验和优势。

(四)C++ 相关问题

  1. C++ 里面哪些操作可能导致 vector 迭代器失效?

    • 答案:在 C++ 中,以下操作可能导致 vector 迭代器失效:
      • 向 vector 中插入或删除元素时,可能会导致指向插入或删除位置之前或之后元素的迭代器失效。
      • 改变 vector 的容量时,如使用 reserve () 或 resize () 函数,可能会导致所有迭代器失效。
  2. C++ 的 vector 是如何扩容的?

    • 答案:当 vector 的大小超过其当前容量时,vector 会进行扩容。通常,vector 的扩容策略是将容量增加一倍。具体的实现方式可能因编译器而异,但一般来说,vector 会重新分配一块更大的内存空间,然后将原有的元素复制到新的内存空间中,并释放旧的内存空间。

(五)系统设计问题

  1. 搜索系统比较大的特点是流量不可预期,假设流量爆发,如何设计架构能使所有请求都回复非空结果?
    • 答案:可以从以下几个方面来设计架构:
      • 热 key 离线计算:
        • 监控热点 key,可以通过统计一段时间内的搜索频率来确定热点 key。可以使用数据结构如哈希表或计数器来记录每个 key 的搜索次数。
        • 增长率监控和搜索量监控,可以设置阈值,当某个 key 的搜索量增长过快或超过一定阈值时,将其标记为热点 key。
        • 对于如何设计数据结构判断它是否是热点 key,可以使用哈希表结合计数器来实现。当一个 key 被搜索时,对应的计数器加一。如果计数器超过一定阈值,则认为该 key 是热点 key。
        • 可以使用数据结构如环形缓冲区或时间窗口来记录上次和本次间隔时间的请求量。每次有新的请求时,将请求量记录到相应的时间窗口中,然后可以根据时间窗口内的请求量来判断是否是热点 key。
      • 分布式流量分配:
        • 可以使用负载均衡算法将流量分配到多个服务器上,以避免单个服务器过载。
        • 可以使用集群技术,如分布式缓存、分布式数据库等,来提高系统的可扩展性和可用性。
      • 兜底降级:
        • 当系统出现故障或流量过大时,可以采取降级措施,如返回默认结果、缓存结果、降低服务质量等。
      • 索引升级:
        • 可以优化索引结构,提高搜索效率。例如,可以使用更高效的索引算法,如 B + 树、哈希索引等。
        • 可以对索引进行分区,将数据分散到多个服务器上,以提高搜索性能。
      • 多级缓存:
        • 可以使用多级缓存来提高系统的响应速度。例如,可以使用内存缓存、分布式缓存等。
        • 可以设置缓存过期时间,以保证缓存中的数据是最新的。
      • 服务器弹性扩展:
        • 可以使用云服务提供商的弹性计算服务,根据流量的变化自动调整服务器的数量。
        • 可以使用容器化技术,如 Docker、Kubernetes 等,来实现快速部署和扩展。

(六)性能问题

  1. redis 单机单线程能抗住多少 qps?
    • 答案:Redis 单机单线程在不同的硬件配置和网络环境下,能抗住的 QPS(Queries Per Second)有所不同。一般来说,在较好的硬件配置下,Redis 单机单线程可以达到几万到十几万的 QPS。但具体的 QPS 还取决于数据的大小、操作的复杂性、网络延迟等因素。

(七)手撕代码

  1. 手撕:将字符串转换为 ASCII 码的十六进制表示,比如 abc 结果为 0x616263。
    • 思路:遍历字符串中的每个字符,将其转换为 ASCII 码的十六进制表示,并拼接在一起。
    • 代码示例(Java):
public class StringToHex {
    public static String stringToHex(String str) {
        StringBuilder hex = new StringBuilder();
        for (char c : str.toCharArray()) {
            hex.append(String.format("0x%02X", (int) c));
        }
        return hex.toString();
    }
}

(八)反问环节

可以询问关于岗位的具体工作内容、团队技术栈、发展机会等问题。

四、总结

通过对这些面经的分析,可以看出字节后端面试涵盖了多个方面的知识,包括编程语言(如 C++、Java、Python)、数据结构与算法、操作系统、数据库、网络协议、系统设计等。在准备面试时,需要全面复习这些知识,并结合实际项目经验进行思考和总结。同时,要注意算法题的练习和代码的规范性,提高自己的编程能力和解决问题的能力。希望本文对求职者有所帮助。

你可能感兴趣的:(java,java,开发语言,go)