原文链接:字节飞书后端二面:简单的一批!_牛客网 (nowcoder.com)
本文仅作为个人学习使用。
数据结构的排序算法有哪些?
-
冒泡排序 (Bubble Sort)
- 算法思想: 比较相邻的两个元素,如果前一个元素比后一个元素大,就交换它们的位置。这个过程会一直重复,直到整个数组都有序。
- 时间复杂度: O(n^2)
-
选择排序 (Selection Sort)
- 算法思想: 遍历数组,找到最小的元素,将其与数组的第一个元素交换位置。然后在剩余未排序的元素中找到最小的元素,将其与数组的第二个元素交换位置。重复这个过程,直到整个数组都有序。
- 时间复杂度: O(n^2)
-
插入排序 (Insertion Sort)
- 算法思想: 将数组分为已排序部分和未排序部分。遍历未排序部分,将每个元素插入到已排序部分的适当位置。
- 时间复杂度: O(n^2)
-
归并排序 (Merge Sort)
- 算法思想: 将数组递归地划分为两半,直到每个子数组只有一个元素。然后将这些子数组合并,形成有序的数组。
- 时间复杂度: O(n log n)
-
快速排序 (Quick Sort)
- 算法思想: 选择一个基准元素,将数组划分为两个子数组:前一个子数组中的所有元素都小于基准元素,后一个子数组中的所有元素都大于基准元素。递归地对这两个子数组进行排序。
- 时间复杂度: 平均情况下 O(n log n),最坏情况下 O(n^2)
-
堆排序 (Heap Sort)
- 算法思想:将数组构建成一个二叉堆,然后将堆顶元素(最大值)与数组的最后一个元素交换,并将数组大小减 1。重复这个过程,直到整个数组都有序。
- 时间复杂度: O(n log n)
-
基数排序(Radix Sort)
-
算法思想:取得数组中的最大数,并判断它有多少位;从低位开始,依次进行一次排序;从最低位开始排序,效率很高,而且改善了占用存储空间大的缺点。分为LSD与MSD,LSD从低位开始,MSD从高位开始。
- 时间复杂度: O(kn), 其中 k 是数据的最大位数, n 是数据的数量。
-
经典的图论算法及使用场景
-
最短路径算法
- 算法: Dijkstra 算法、Bellman-Ford 算法、Floyd-Warshall 算法
- 应用场景:
- 路径规划: 用于规划最短的交通路径或物流路径,如导航系统、快递路径优化等。
- 社交网络分析: 用于分析两个用户之间的最短联系路径,如好友推荐、关系链分析等。
- 网络优化: 用于优化网络拓扑结构,如路由器之间的最短连接路径等。
-
最小生成树算法
- 算法: Kruskal 算法、Prim 算法
- 应用场景:
- 网络优化: 用于构建通信网络、电力网络等最小成本的连通网络。
- 图像分割: 用于将图像划分为不同区域,在计算机视觉中有广泛应用。
- 物流规划: 用于规划仓储配送中心的最优连接方式,降低成本。
-
拓扑排序算法
- 算法: 基于 DFS 或 BFS 的拓扑排序算法
- 应用场景:
- 任务调度: 用于确定任务的执行顺序,如课程安排、项目管理等。
- 依赖关系分析: 用于分析软件模块、工艺流程等之间的依赖关系。
- 数据库事务管理: 用于管理事务之间的依赖关系,确保事务的正确执行顺序。
-
连通性算法
- 算法: DFS、BFS、Union-Find 算法
- 应用场景:
- 社交网络分析: 用于识别社交网络中的连通子图,如社区发现、影响力分析等。
- 图像分割: 用于识别和分割图像中的连通区域,如object detection、semantic segmentation等。
- 网络故障诊断: 用于确定网络中故障节点和连通域,提高网络可靠性。
如何判断有向图是否有环?
-
基于 DFS 的方法:
- 思路:
- 对图进行深度优先搜索 (DFS),给节点设置三个状态(未访问、正在访问、已访问),初始化全部为未访问。
- 在递归过程中,刚进入递归的节点设置为正在访问,该节点递归结束设为已访问, 如果递归过程中发现某个节点的访问状态为正在访问 ,则说明存在环。
- 如果所有节点都被访问完且没有发现环,则说明图是无环的。
- 时间复杂度: O(V+E),其中 V 为节点数,E 为边数。
- 思路:
-
基于拓扑排序的方法:
- 思路:
- 对图进行拓扑排序。
- 如果拓扑排序成功,则说明图是无环的;如果拓扑排序失败(即无法找到拓扑顺序),则说明图存在环。
- 时间复杂度: O(V+E)。
- 思路:
更高级的树的算法
-
二叉树 (Binary Tree)
- 特点: 每个节点最多有两个子节点的树形数据结构。
- 应用场景:
- 用于实现表达式求值、文件系统目录等。
- 作为其他树形数据结构的基础,如二叉搜索树、AVL树、红黑树等。
-
二叉搜索树 (Binary Search Tree, BST)
- 特点: 左子树上所有节点的值小于根节点,右子树上所有节点的值大于根节点。
- 应用场景:
- 用于快速查找、插入和删除元素。
- 可用于实现关联数组等数据结构。
-
平衡二叉树 (Balanced Binary Tree)
- 特点: 左右子树高度差不超过 1 的二叉搜索树,能保证查找、插入、删除的时间复杂度为 O(log n)。
- 应用场景:
- 用于实现高性能的关联数组,如 Java 的 TreeMap 和 TreeSet。
- 在文件系统、数据库索引等领域使用。
-
红黑树 (Red-Black Tree)
- 特点: 一种自平衡二叉搜索树,通过颜色约束来实现平衡,时间复杂度为 O(log n)。
- 应用场景:
- 用于实现关联数组,如 Java 的 TreeMap 和 TreeSet。
- 在虚拟内存管理、文件系统索引等领域使用。
-
B 树 (B-Tree) 和 B+ 树 (B+-Tree)
- 特点: 多路平衡查找树,适用于磁盘等大容量存储设备。B 树在内部节点存储数据,B+ 树只在叶子节点存储数据。
- 应用场景:
- 用于实现文件系统和数据库索引,如 MySQL 的 InnoDB 引擎。
- 用于外部排序算法中的磁盘管理。
- 应用于大型网络搜索引擎的索引结构。
总的来说,这些树型数据结构在计算机科学的各个领域都有广泛的应用,包括但不限于数据库、文件系统、信息检索、机器学习等。它们在保证高效查询、插入、删除等操作的同时,也兼顾了空间利用率和容错性等特点。
字典树了解吗?他有什么用途?
可参考:【数据结构】字典树TrieTree图文详解-CSDN博客
字典树(Trie,也称前缀树)是一种树形的数据结构,用于高效地存储和检索字符串数据集合。
具体特点
- 根节点不包含字符,从第二层节点开始代表一个字符。
- 从根节点到某一节点,将经过的字符连接起来就得到一个字符串。
- 每个节点的所有子节点包含的字符都不相同。
结构优点
- 高效的前缀搜索和查找。在字典树上搜索一个字符串的时间复杂度是O(k),其中k是字符串的长度。
- 节省内存空间。字典树可以共享字符串的公共前缀,相比于使用链表或数组存储字符串集合能够节省大量内存。
- 方便单词的枚举和排序。字典树天然支持字典序遍历。
典型应用
- 搜索引擎的关键词提示和自动补全。
- 拼写检查器和纠错器。
- IP路由表存储和检索。
- 数据压缩中的应用。
介绍一下HTTP协议
HTTP (Hypertext Transfer Protocol) 是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是 Web 应用程序中最基础和最重要的协议之一。
HTTP 协议的主要特点和功能
-
请求-响应模型:HTTP 定义了客户端(通常是浏览器)如何向服务器发送请求,以及服务器如何响应这些请求。
-
无状态性:HTTP 是一种无状态协议,这意味着每次请求都是独立的,服务器不会保留之前请求的任何信息。
-
方法(动词):HTTP 定义了几种请求方法,如 GET、POST、PUT、DELETE 等,用于指定客户端需要执行的操作。
-
状态码:服务器通过状态码(如 200 OK、404 Not Found、500 Internal Server Error)来告知客户端请求的结果。
-
头部(Header):HTTP 头部包含了有关请求和响应的元数据,如内容类型、缓存控制、身份验证等。
-
报文格式:HTTP 请求和响应报文都由起始行、头部和消息体(可选)组成。
-
连接管理:HTTP 支持持久连接和管线化,可以复用 TCP 连接来提高性能。
-
HTTPS:HTTPS 是在 HTTP 的基础上加入了 SSL/TLS 加密层,可以提供安全的通信通道。
OSI (Open Systems Interconnection) 参考模型
一个概念性的网络协议栈,分为以下 7 个层次:
- 物理层 (Physical Layer)
- 数据链路层 (Data Link Layer)
- 网络层 (Network Layer)
- 传输层 (Transport Layer)
- 会话层 (Session Layer)
- 表示层 (Presentation Layer)
- 应用层 (Application Layer)
HTTP 作为一种应用程序使用的协议,位于 OSI 参考模型的最高层 - 应用层。
应用层是最靠近用户应用程序的一层,它定义了各种网络服务和应用程序协议,如 HTTP、FTP、SMTP 等。这一层协议负责处理应用程序之间的通信和数据交换。
因此, HTTP 协议是位于 OSI 参考模型应用层的一种网络协议,它定义了 Web 浏览器与 Web 服务器之间的通信规则和数据格式。
除了 HTTP,其他常见的应用层协议还包括 DNS、DHCP、SMTP、POP3、IMAP 等。这些协议都位于 OSI 模型的应用层,负责应用程序之间的通信和数据交换。
HTTP1.0、1.1、2.0以及未来规划的3.0有什么区别和联系
-
HTTP/1.0
- 最早的 HTTP 版本,1996 年发布。
- 每个 HTTP 请求都需要建立一个新的 TCP 连接。
- 不支持持久连接,每次请求都需要重新建立和断开连接。
- 无法复用已建立的连接来发送多个请求。
-
HTTP/1.1
- 1999 年发布,是目前使用最广泛的 HTTP 版本。
- 引入了持久连接(persistent connection)的概念。
- 支持一个 TCP 连接上发送多个 HTTP 请求和响应。
- 引入了管线化(pipelining)机制,可以并行发送多个请求。
- 增加了缓存控制、断点续传等新功能。
-
HTTP/2.0
- 2015 年发布,是 HTTP 协议的重大升级。
- 采用二进制协议,而不是文本协议,提高了传输效率。
- 支持多路复用(multiplexing),允许在同一个 TCP 连接上发送多个请求和响应。
- 引入了头部压缩,减少了传输开销。
- 支持服务器推送(server push)功能,可以主动向客户端推送资源。
-
HTTP/3.0 (QUIC)
- 目前正在开发中的 HTTP 下一代协议。
- 将基于 UDP 协议,而不是传统的 TCP 协议。
- 旨在解决 TCP 协议在移动网络下的一些缺陷,如连接建立延迟高、不适合短连接等。
- 将提供更快的连接建立、更好的拥塞控制、更低的延迟等优势。
总的来说,HTTP 协议版本的演进主要体现在以下几个方面:
- 提高传输效率和性能,减少延迟和开销。
- 支持更丰富的功能,如缓存控制、服务器推送等。
- 针对新的网络环境和应用场景进行优化,如移动互联网。
IO多路复用
IO 多路复用是一种提高 I/O 操作效率的重要技术。它可以在单线程中同时监控和处理多个 I/O 事件,避免线程在等待 I/O 操作完成时被阻塞。常见的 IO 多路复用技术包括:
-
Select:
- 最早的 I/O 多路复用技术之一。
- 通过监听多个文件描述符集合(读、写、异常),当任何一个集合中的事件发生时,select 函数会返回。
- 缺点是文件描述符数量受限制,且每次调用都需要遍历整个集合。
-
Poll:
- 与 select 类似,但使用动态分配的 pollfd 结构体来监听文件描述符。
- 可以监听更多的文件描述符,且无需遍历整个集合。
- 但仍然需要在每次调用时扫描整个 pollfd 集合。
-
Epoll:
- Linux 特有的 I/O 多路复用技术,提供了更好的性能。
- 采用事件驱动的模型,不需要遍历整个集合。
- 可以监听更多的文件描述符,且可以对事件进行更细粒度的控制。
-
Kqueue:
- BSD 系统上的 I/O 多路复用技术,类似于 epoll。
- 提供了事件驱动的 I/O 监控,可以监控多种类型的事件,如文件 I/O、进程事件等。
IO 多路复用技术有以下几个主要的优势:
-
提高 I/O 操作效率:
- 通过同时监控和处理多个 I/O 事件,避免了线程在等待 I/O 操作完成时被阻塞。
- 这样可以大大提高 I/O 操作的并发性和效率。
-
减少资源消耗:
- 相比于为每个 I/O 操作创建一个单独的线程,IO 多路复用技术可以在单个线程中完成多个 I/O 操作。
- 这样可以减少线程创建和切换的开销,降低系统资源的消耗。
-
提高可伸缩性:
- 在高并发的网络服务器等场景中,IO 多路复用技术可以支持处理大量的并发 I/O 事件。
- 这使得应用程序能够更好地应对高并发负载,提高系统的可伸缩性。
-
事件驱动模型:
- 现代 IO 多路复用技术(如 epoll 和 kqueue)采用事件驱动的模型,不需要主动轮询检查 I/O 事件的发生。
- 这种模型可以更高效地监控和响应 I/O 事件,减少不必要的系统调用和资源消耗。
-
跨平台支持:
- 虽然不同操作系统提供了不同的 IO 多路复用技术(如 select、poll、epoll、kqueue 等),但它们都遵循相似的编程接口。
- 这使得基于 IO 多路复用的应用程序可以跨平台运行,提高了开发的灵活性。
总的来说,IO 多路复用技术是提高 I/O 操作效率、减少系统资源消耗、提高应用程序可伸缩性的重要手段。它广泛应用于网络服务器、数据库、游戏服务器等高并发 I/O 场景中。
介绍一下你知道的操作系统的知识
可以参考:3.1 Linux 内核 vs Windows 内核 | 小林coding (xiaolincoding.com)
-
操作系统结构
- 单内核(Monolithic)结构: 所有功能集成在一个内核中,如Linux内核。优点是执行效率高,缺点是内核臃肿,难以扩展。
- 微内核(Microkernel)结构: 内核只提供最基本功能,其他服务在用户态实现,如macOS和Windows NT。优点是灵活可扩展,缺点是性能略有损失。
- 分层(Layered)结构: 分为硬件层、内核层、中间件层和应用层,如macOS和Windows。优点是模块化设计,缺点是层间调用开销较大。
-
内存管理
- 虚拟内存: 通过页面置换算法实现程序地址空间和物理内存的动态映射。
- 分页和分段: 将内存分成固定大小的页面或可变大小的段,提高利用率和灵活性。
- 内存分配算法: 如首次适应、最佳适应、最坏适应等,用于分配和回收内存块。
-
进程管理
- 进程的概念: 程序的运行实例,拥有独立的地址空间和执行上下文。
- 进程控制块: 描述进程状态和属性的数据结构。
- 进程调度: 调度算法如FCFS、SJF、优先级调度、时间片轮转等。
-
设备管理
- 设备驱动程序: 为设备提供统一的软件接口。
- 缓冲区管理: 解决CPU和设备速度差异带来的问题。
- 设备分配与回收: 合理分配和及时回收设备资源。
-
文件系统
- 文件组织: 目录、文件属性、访问控制。
- 文件存储: 磁盘分区、文件分配表、索引结点。
- 文件操作: 创建、删除、读写、打开关闭等。
-
网络系统
- 协议栈: TCP/IP、UDP、IP、MAC等各层协议。
- 网络设备驱动: 网卡设备的软件接口。
- 路由算法: 如最短路径、负载均衡等。
进程和线程是怎么切换的
-
进程切换
- 进程切换发生在操作系统内核中,由操作系统调度器负责。
- 当一个进程耗尽时间片或被阻塞时,调度器会选择另一个就绪进程来运行。
- 进程切换涉及以下步骤:
- 保存当前进程的执行上下文(如PC、寄存器、栈等)
- 选择待运行的进程
- 恢复待运行进程的执行上下文
- 切换CPU控制权,让新进程开始执行
-
线程切换
- 线程是进程中的执行单元,线程切换比进程切换更加高效。
- 线程切换通常发生在以下情况:
- 时间片用完,轮到其他就绪线程运行
- 线程主动让出CPU,如调用sleep()
- 线程被阻塞,如等待I/O完成
- 线程切换过程:
- 保存当前线程的执行上下文
- 选择待运行的线程
- 恢复待运行线程的执行上下文
- 切换CPU控制权
-
上下文切换开销
- 进程切换比线程切换开销大,因为需要保存/恢复整个地址空间。
- 线程切换只需保存/恢复轻量级的执行上下文,如寄存器和栈指针。
- 频繁的上下文切换会增加系统开销,降低性能。因此操作系统会尽量减少不必要的切换。
了解过协程吗
协程(Coroutine)是一种非常轻量级的用户态线程,它们与操作系统内核无关,由应用程序自行管理。协程的主要特点和工作方式如下:
-
协程的概念
- 协程是一种"半线程"或"微线程",比线程更加轻量级。
- 协程由程序员显式地定义切换点,不受操作系统调度的约束。
- 协程可以在单线程内并发执行,彼此间可以相互切换。
-
协程的优势
- 创建和切换协程的开销很小,比线程低很多。
- 协程适合于IO密集型任务,可以使用异步I/O提高性能。
- 协程可以方便地实现并发控制,如生产者-消费者模型。
- 协程编程模型简单易懂,易于理解和编写。
-
协程的工作原理
- 协程由控制流、局部状态和栈组成。
- 协程可以通过yield语句主动让出CPU,切换到其他协程执行。
- 协程恢复执行时,会从yield处继续执行。
-
协程的实现
- 协程可以用各种语言实现,如Python的gevent、Golang的goroutine等。
- 协程库通常提供yield、resume等基本操作,用于在协程间切换。
- 协程可以配合异步I/O等技术,实现高并发网络服务。
总之,协程是一种轻量级的并发编程模型,它通过显式的切换点,提供了比线程更加高效的并发方式。协程广泛应用于I/O密集型程序,如Web服务器、爬虫等。
数据从内存写到磁盘是怎么样的一个过程?CPU读数据又是怎样的一个过程?(面试官想问的是DMA)
数据从内存写到磁盘的过程通常是通过DMA(Direct Memory Access)实现的,具体流程如下:
-
CPU发出写磁盘的指令:
- CPU将需要写入磁盘的数据复制到系统总线上预留的一块缓冲区。
- CPU同时告诉DMA控制器,需要把这些数据写入磁盘的某个位置。
-
DMA控制器接管内存访问权:
- DMA控制器从CPU手中获取访问内存的权限,不需要CPU参与。
- DMA控制器直接从内存缓冲区读取数据,不占用CPU资源。
-
DMA控制器直接写入磁盘:
- DMA控制器将数据通过磁盘控制器直接写入磁盘,完成I/O操作。
- 整个过程CPU不需要参与,可以去处理其他任务,提高系统吞吐量。
-
DMA传输完成后发出中断:
- 数据传输完成后,DMA控制器会向CPU发出中断信号。
- CPU接收到中断后,检查I/O操作是否完成,然后继续后续处理。
CPU读取数据的过程与写入类似,同样使用DMA实现:
- CPU发出读磁盘的指令,告诉DMA控制器从磁盘某个位置读取数据。
- DMA控制器接管内存访问权,直接从磁盘读取数据到内存缓冲区。
- DMA传输完成后发出中断,CPU接收到中断后处理读取到的数据。
总之,DMA技术可以让CPU不直接参与内存和磁盘的数据传输,大大提高了I/O操作的效率。
算法题
第一题(0-1背包问题)
给你一个大小为10的整数数组和一个目标值target,每个数只能用一次,判断是否能用数组中的某些整数相加得到目标值target。
第二题(课程表LeetCode 207)