网站首页 > 文章精选 正文
在面试字节跳动的过程中,现场写算法代码是绕不开的一个环节。其中快速排序(Quick Sort)、快速选择(Quick Select)是最常见的算法题之一。快速选择是目前解决TopK问题的最优算法,如果想拿下字节跳动的offer,快速排序算法是必须要掌握的算法之一!
开篇先出到面试题,请读者思考一下可能的解法:
给你一个无序数组,请找出其中第K大的数,时间复杂度控制在O(N)。
如果不对时间复杂度加约束的情况下,该题有很多种可能解法,例如:
- 用任意一种性能不错的排序算法先将数组进行排序,然后从中找到位置k的数值。但即便用当前最好的排序算法,时间复杂度也是在O(n·log n)的级别,不符合题目要求。
- 用大顶堆算法,仅保留K个最大的值。这种算法的时间复杂度虽然优于前面一种,但时间复杂度也是O(n·log k)的级别,依然不满足题目要求。
因此,为了达到题目中要求,就必须要引出今天的主角:快速选择算法(Quick Select)。快速选择算法是目前解决TopK问题的最优解。其核心思想和快速排序类似,因为这两个经典算法的提出者都是同一个人——C.A.R.Hoare。
快速选择的执行步骤是先从数组中随机选择一个元素作为pivot,然后遍历数组,将<pivot的元素都放在pivot左侧,≥pivot的元素都放在pivot右侧。如此遍历完以后,如果要找第k大的数,可以判断pivot两侧元素个数。假设pivot右侧元素个数≥k可推断出,第k大的数一定在pivot右侧的元素中,因此拿pivot右侧部分作为新数组重新进行一轮找出第k大元素的快速选择即可。若pivot右侧元素个数<k,可知,第k大的数一定在pivot左侧,因此以pivot左侧所有元素作为新数组,重新进行一轮快速选择,但是k的值就变为k-右侧元素个数,因为最大的若干个元素都在pivot右侧中,所以要从k中减去这些右侧元素的个数。
以下是一个快速选择的示例:
以下是基于Java实现的快速选择的代码,仅供参考:
public int findTopK(int[] nums, int k, int start, int end) {
if (k <= 0) {
throw new IllegalArgumentException("K can not less than 1!");
} else if (k > (end - start + 1)) {
throw new IllegalArgumentException("K out of range! start = " + start + ", end = " + end + ", k = " + k);
}
if (k == 1) {
int max = Integer.MIN_VALUE;
for (int i = start; i <= end; i++) {
max = Math.max(max, nums[i]);
}
return max;
}
int rand = new Random().nextInt(k);
int tmp = nums[end];
nums[end] = nums[start + rand];
nums[start + rand] = tmp;
int pivot = nums[end];
int l = start, r = start;
while (r < end) {
if (nums[r] > pivot) {
r++;
} else {
tmp = nums[r];
nums[r] = nums[l];
nums[l] = tmp;
l++;
r++;
}
}
tmp = pivot;
nums[end] = nums[l];
nums[l] = tmp;
if (start + (end - start + 1) - l >= k) {// 若右侧(含l)数量≥k
return findTopK(nums, k, l, end);
} else {// 右侧(含l)数量不足k
return findTopK(nums, k - (end - l + 1), start, l - 1);
}
}
快速选择的时间复杂度是O(n),推论依据是快速选择每次遍历的元素个数预期都会减半,因此全部要遍历的元素个数是:
Sn = n + n/2 + n/4 + …… + 1
这是一个典型的等比数列求和,套用等比数列求和公式可得:
Sn = n + n/2 + n/4 + …… + 1 = (a1 - an · q) / (1 - q)= (n - 0.5) / 0.5 = 2n - 1
去除不必要的常数,仅保留数量级之后可得,快速排序的预期时间复杂度是O(n)
现如今互联网求职竞争越发激烈,难度越发困难,如果不做好充足的复习,很可能会丧失宝贵的面试机会!关注我,定期高频更新优质面试宝典,帮助你在职场中平步青云,斩获理想offer!
猜你喜欢
- 2025-06-24 我通过了字节的技术面,但最后还是没通过
- 2025-06-24 字节跳动HR实习生:面经和碎碎念(字节跳动hr实习生岗位)
- 2025-06-24 面试直通车|字节跳动设计大赛来啦,6w现金等你拿
- 2025-06-24 花2个月时间整理了3.5万字的自动化测试面试题(有答案,很详细)
- 2025-06-24 老码农的字节跳动前端面试总结(字节跳动前端面试题及答案)
- 2025-06-24 2023年200多道Java基础面试题(java面试基础笔试题)
- 2025-06-24 第一次凡尔赛,字节跳动3面+腾讯6面一次过,谈谈我的大厂面经
- 2025-06-24 我的天!字节跳动面试竟然问了这道题
- 2025-06-24 人力实习生面试分享(字节、猿辅导、拼多多、银行等)
- 2025-06-24 「字节跳动测试开发面经」一二三面+hr面+超级多干货+复习资料
- 06-24PLC常用进制数及转换方法(plc中进制符号)
- 06-24PLC常用数制及转换方法,让你轻松掌握PLC编程
- 06-24PLC编程必看!5种常见进制数解析,搞懂才能玩转PLC!
- 06-24C数据类型——常量(c的数据类型及其定义方法)
- 06-24什么是二进制、八进制、十进制、十六进制?
- 06-24理论基础——十进制、二进制、十六进制、八进制
- 06-24搞不懂PLC中的高字节、低字位是啥?看完这篇文章就懂了!
- 06-242、进位制之间的转换(含有小数位)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)