天鹏恒宇面试
快速排序和冒泡排序的时间复杂度
冒泡排序(Bubble Sort):
- 最坏时间复杂度: O(n^2) – 在数组完全逆序的情况下,每次比较和交换都会发生。
- 平均时间复杂度: O(n^2) – 对于任何情况,平均时间复杂度都是 O(n^2)。
- 最好时间复杂度: O(n) – 当数组已经有序时,只需要进行一次遍历。
快速排序(Quick Sort):
- 最坏时间复杂度: O(n^2) – 当每次选择的基准元素都是当前子数组中的最大或最小元素时。
- 平均时间复杂度: O(n log n) – 在平均情况下,快速排序的性能较好。
- 最好时间复杂度: O(n log n) – 当每次选择的基准元素都能平均地将数组分成两半时。
快速排序和冒泡排序的优缺点
- 算法思想:
- 冒泡排序:通过重复遍历待排序的元素,比较相邻元素,并在不符合顺序的情况下交换它们,直到整个数组有序。
- 快速排序:使用分治法的思想,选择一个基准元素,将数组分为两个子数组,使得左边的元素都小于基准,右边的元素都大于基准,然后递归地对子数组进行排序。
- 性能:
- 冒泡排序的平均和最坏时间复杂度都是O(n^2),因此不适用于大规模数据的排序。
- 快速排序的平均时间复杂度为O(n log n),在实践中通常比冒泡排序更快。但最坏情况下可能达到O(n^2),取决于选择的基准元素。
- 稳定性:
- 冒泡排序是稳定的,相等元素的相对位置不会改变。
- 快速排序在一般情况下是不稳定的,因为在交换过程中相等元素的相对位置可能会改变。
- 空间复杂度:
- 冒泡排序是原地排序算法,只需要常数级别的额外空间。
- 快速排序在递归实现时需要额外的栈空间,因此空间复杂度较高。
- 适用场景:
- 冒泡排序适用于小型数据集,或者在其他排序算法不适用的特殊情况。
- 快速排序适用于大型数据集,是常用的高效排序算法之一。
什么是链表,什么是线性表
线性表:
- 定义: 线性表是一种数据结构,其中元素排列成一条线,具有唯一的首元素和唯一的尾元素。线性表中的元素之间存在直接关系,即每个元素都有一个前驱元素和一个后继元素,除了首元素没有前驱,尾元素没有后继。
- 实现: 线性表可以通过数组或链表来实现。数组是一块连续的内存空间,元素的存储位置是相邻的;链表是一种非连续的数据结构,元素通过指针相连。
- 存储特性: 线性表的元素在内存中是按线性顺序存储的,可以通过索引(或位置)来访问元素。
链表:
- 定义: 链表是一种线性表的实现方式,其中元素的存储位置不一定是相邻的,而是通过指针相连的。每个元素都包含一个数据项和一个指向下一个元素的指针。
- 结构: 链表包括单链表、双链表和循环链表等。在单链表中,每个节点有一个指向下一个节点的指针;在双链表中,每个节点有一个指向前一个节点和一个指向下一个节点的指针;在循环链表中,最后一个节点指向第一个节点,形成一个环。
- 灵活性: 由于链表不要求内存空间连续,插入和删除元素相对容易,不需要移动其他元素。这使得链表在某些操作上比数组更灵活。
- 缺点: 与数组相比,链表的随机访问速度较慢,因为必须通过指针一个节点一个节点地遍历。同时,链表需要额外的存储空间来存储指针。
查询、插入、删除数据,哪个表的效率高
- 线性表:
- 线性表是一种按照线性顺序存储数据的数据结构,数组是一种常见的线性表实现。在线性表中,元素在内存中是相邻存储的,因此通过索引可以快速访问元素。对于查询来说,线性表的查询操作是O(1)的时间复杂度,即常数时间。
- 插入和删除操作涉及到元素的移动,特别是在数组中插入或删除元素时,需要移动后续元素,平均时间复杂度为O(n),其中n是元素的个数。
- 链表:
- 链表是一种非连续存储的数据结构,元素通过指针相互连接。在链表中,查询操作相对较慢,因为需要从头节点开始逐个遍历找到目标元素,平均时间复杂度为O(n)。
- 插入和删除操作在链表中比较高效,特别是在双向链表中。在链表中插入或删除元素时,只需要调整相邻元素的指针,平均时间复杂度为O(1)。
综合来看,如果主要操作是查询,并且数据规模较大,线性表的效率可能更高。如果主要操作是插入和删除,并且需要频繁地进行这些操作,链表可能更适合。
MySQL的时间函数知道哪些
-
NOW():
- 返回当前日期和时间的值,包括年、月、日、小时、分钟和秒。
SELECT NOW();
-
CURDATE():
- 返回当前日期的值,不包括时间。
SELECT CURDATE();
-
CURTIME():
- 返回当前时间的值,不包括日期。
SELECT CURTIME();
-
DATE():
- 从日期时间值中提取日期部分。
SELECT DATE(NOW());
-
TIME():
- 从日期时间值中提取时间部分。
SELECT TIME(NOW());
-
YEAR():
- 从日期或日期时间值中提取年份。
SELECT YEAR(NOW());
-
MONTH():
- 从日期或日期时间值中提取月份。
SELECT MONTH(NOW());
-
DAY():
- 从日期或日期时间值中提取日。
SELECT DAY(NOW());
-
HOUR():
- 从时间或日期时间值中提取小时。
SELECT HOUR(NOW());
-
MINUTE():
- 从时间或日期时间值中提取分钟。
SELECT MINUTE(NOW());
-
SECOND():
- 从时间或日期时间值中提取秒。
SELECT SECOND(NOW());
-
DATEDIFF():
- 返回两个日期之间的天数差。
SELECT DATEDIFF('2023-01-01', '2022-01-01');
-
DATE_ADD():
- 在日期或日期时间上添加一个时间间隔。
SELECT DATE_ADD(NOW(), INTERVAL 1 DAY);
-
DATE_SUB():
- 从日期或日期时间中减去一个时间间隔。
SELECT DATE_SUB(NOW(), INTERVAL 1 WEEK);
MySQL的存储过程
MySQL 存储过程是一组预先编译的 SQL 语句,可以在 MySQL 数据库中保存和重复使用。存储过程可以包含 SQL 语句、控制结构(例如条件和循环)、变量、参数和错误处理等元素。通过使用存储过程,可以将复杂的业务逻辑封装在数据库中,提高代码的可维护性和执行效率。
以下是 MySQL 存储过程的基本结构:
DELIMITER //
CREATE PROCEDURE procedure_name (parameter_list)
BEGIN
-- SQL statements
END //
DELIMITER ;
DELIMITER
用于更改 SQL 语句的结束标志,以便在存储过程中使用分号 (;
)。在定义存储过程时,需要用//
作为结束标志,而在存储过程内部的 SQL 语句结束时,可以使用普通的分号。CREATE PROCEDURE
用于创建存储过程。procedure_name
是存储过程的名称。parameter_list
是存储过程的参数列表,包括参数的名称和数据类型。BEGIN...END
之间是存储过程的主体,包含了一系列 SQL 语句和控制结构。//
用于结束存储过程的定义。DELIMITER ;
用于恢复 SQL 语句的结束标志为分号。
百万量级的数据需要进行连表查询,可能出现数据断层,如何解决,让数据量变小
- 使用索引:
- 确保参与联表查询的列都有索引,这有助于加速查询过程。在 MySQL 中,可以使用
CREATE INDEX
语句创建索引。
- 确保参与联表查询的列都有索引,这有助于加速查询过程。在 MySQL 中,可以使用
- 分页查询:
- 将大查询拆分成多个小查询,每次只查询一部分数据,这可以通过分页来实现。在很多情况下,用户不需要一次性看到全部的数据,分页查询可以提供更好的用户体验。
- 使用合适的字段:
- 只查询需要的字段,而不是选择全部字段。这可以减小传输的数据量,提高查询性能。
- (只认可了这个)
- 使用合适的数据类型:
- 使用较小的数据类型来存储数据,以减小存储空间和提高查询性能。
- 缓存查询结果:
- 如果查询的数据不经常变化,可以考虑使用缓存技术,将查询结果缓存起来,避免每次都执行查询操作。
- 分库分表:
- 考虑将数据按照某种规则分散到多个数据库或者多个表中,以减小单个查询的数据量。
- 使用数据库优化工具:
- 使用数据库的性能分析工具,如MySQL的
EXPLAIN
语句,来分析查询语句的执行计划,以便优化查询性能。
- 使用数据库的性能分析工具,如MySQL的
- 数据压缩:
- 对于需要传输的大量数据,可以考虑使用数据压缩技术,减小传输的数据量。
- 使用合适的连接方式:
- 根据查询的需求选择合适的连接方式,如 INNER JOIN、LEFT JOIN 等。不同的连接方式对性能有不同的影响。
- 数据库服务器优化:
- 确保数据库服务器的硬件和配置足够支持大数据量的查询,例如增加内存、优化磁盘读写速度等。
webappi接口的协议
- HTTP/HTTPS:
- 绝大多数 Web API 使用 HTTP(Hypertext Transfer Protocol)或其加密版本 HTTPS 来进行通信。HTTP是一种无状态的协议,通过请求-响应的方式进行通信。RESTful API(Representational State Transfer)是一种基于 HTTP 协议的常见设计风格,它使用 HTTP 方法(GET、POST、PUT、DELETE等)对资源进行操作。
- SOAP(Simple Object Access Protocol):
- SOAP 是一种基于 XML 的协议,用于在计算机网络上交换结构化的信息。它定义了一种通信的框架,允许在不同的操作系统和编程语言之间进行通信。相对于 REST,SOAP 更为庞大,支持更多的功能,但也因此更为复杂。
- WebSocket:(可算可不算)
- WebSocket 是一种在单个 TCP 连接上提供全双工通信的协议。与 HTTP 不同,WebSocket 允许在客户端和服务器之间建立持久连接,实时推送数据。这使得它适用于需要实时性的应用,如即时通讯和实时数据更新。
TCP协议四次挥手
- 第一次挥手(Client -> Server):
- 客户端发送一个带有 FIN(Finish)标志的TCP报文段,表示它已经完成数据的发送。
- 第二次挥手(Server -> Client):
- 服务器接收到客户端的 FIN 报文段,会发送一个 ACK(Acknowledgment)报文段,表示已经收到了客户端的关闭请求。
- 第三次挥手(Server -> Client):
- 服务器发送一个带有 FIN 标志的TCP报文段,表示服务器已经完成数据的发送。
- 第四次挥手(Client -> Server):
- 客户端接收到服务器的 FIN 报文段,会发送一个 ACK 报文段,表示已经收到了服务器的关闭请求。
接口前端调用为什么会产生跨域
- 协议不同:
- 当前网页使用的协议(http或https)与请求的资源使用的协议不同,就会发生跨域。例如,一个页面使用https协议,但请求一个使用http协议的接口。
- 域名不同:
- 当前网页的域名与请求的资源的域名不同,就会发生跨域。例如,一个页面在
www.example.com
域下,但请求了api.example-api.com
域下的接口。
- 当前网页的域名与请求的资源的域名不同,就会发生跨域。例如,一个页面在
- 端口不同:
- 当前网页的端口与请求的资源的端口不同,也会发生跨域。例如,一个页面在
www.example.com:8080
域下,但请求了www.example.com:3000
域下的接口。
- 当前网页的端口与请求的资源的端口不同,也会发生跨域。例如,一个页面在
- 子域名不同:
- 即使是不同的子域名,也会被认为是跨域。例如,一个页面在
app.example.com
域下,但请求了api.example.com
域下的接口。
- 即使是不同的子域名,也会被认为是跨域。例如,一个页面在
输出字符串“兰州文理学院”中的“文理学院”有几种方式
-
字符串截取:
- 使用
substring
方法可以截取字符串的指定部分。
String originalString = "兰州文理学院"; String targetString = originalString.substring(2); // 从索引为2的位置开始截取,得到"文理学院" System.out.println(targetString);
- 使用
-
正则表达式匹配:
- 使用正则表达式来匹配目标字符串。
import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { String originalString = "兰州文理学院"; String regex = "文理学院"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(originalString); if (matcher.find()) { String targetString = matcher.group(); System.out.println(targetString); } } }
-
字符串查找:
- 使用
indexOf
方法查找目标字符串在原始字符串中的位置。
String originalString = "兰州文理学院"; int index = originalString.indexOf("文理学院"); if (index != -1) { String targetString = originalString.substring(index); System.out.println(targetString); }
- 使用
-
使用
split
方法:String originalString = "兰州文理学院"; String[] parts = originalString.split("文理学院"); if (parts.length > 1) { String targetString = parts[1]; System.out.println(targetString); }
-
将字符串转换为字符数组:
String originalString = "兰州文理学院"; char[] arr = originalString.toCharArray(); for(int i = 2; i <= 5; i ++){ System.out.print(arr[i]); }
Was this helpful?
0 / 0