215. 数组中的第K个最大元素
1、题目
给定整数数组 nums
和整数 k
,请返回数组中第 k
个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
你必须设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入: [3,2,1,5,6,4], k = 2 输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4 输出: 4
提示:
1 <= k <= nums.length <= 105
-104 <= nums[i] <= 104
Related Topics
- 数组
- 分治
- 快速选择
- 排序
- 堆(优先队列)
2、题目分析
借助快排的分治思想,找到区间支点,再判断支点所在位置是否为第k大的位置
3、复杂度最优解代码示例
public int findKthLargest(int[] nums, int k) {
// 使用快速选择算法,类似于快速排序的思想
// 调整k为索引,因为找的是第K个最大元素,而索引是从0开始的
k = nums.length - k;
int left = 0;
int right = nums.length - 1;
while (left < right) {
// 划分数组,获取划分点的索引
int pivotIndex = partition(nums, left, right);
// 判断划分点的索引是否等于k,如果是则找到第K个最大元素
if (pivotIndex == k) {
return nums[pivotIndex];
} else if (pivotIndex < k) {
// 如果划分点的索引小于k,则说明第K个最大元素在右边,缩小右边界
left = pivotIndex + 1;
} else {
// 如果划分点的索引大于k,则说明第K个最大元素在左边,缩小左边界
right = pivotIndex - 1;
}
}
// 如果left等于right,或者while循环结束后left大于right,则说明已经找到第K个最大元素
return nums[left];
}
private int partition(int[] nums, int low, int high) {
// 选择最左边的元素作为基准值
int pivot = nums[low];
// 遍历数组,将小于基准值的元素放到左边,大于基准值的元素放到右边
while (low < high) {
// 在右侧找到第一个小于基准值的元素
while (low < high && nums[high] >= pivot) {
high--;
}
// 将该元素放到左侧
nums[low] = nums[high];
// 在左侧找到第一个大于基准值的元素
while (low < high && nums[low] <= pivot) {
low++;
}
// 将该元素放到右侧
nums[high] = nums[low];
}
// 将基准值放到正确的位置上
nums[low] = pivot;
return low; // 返回基准值的索引
}
4、适用场景
-
数据分析:在处理大量数据时,找出第K个最大元素可以帮助我们了解数据的分布情况,例如在销售数据中找出销售额排名第K的商品。
-
算法设计:在设计一些需要排序的算法时,如快速排序、堆排序等,找出第K个最大元素可以作为算法的一部分。
-
游戏开发:在一些游戏中,可能需要找出得分排名第K的玩家,这时就需要找出数组中的第K个最大元素。
-
网络编程:在网络编程中,可能需要找出传输速度排名第K的节点,这时也需要找出数组中的第K个最大元素。
-
机器学习:在机器学习中,可能需要找出预测结果排名第K的模型,这时也需要找出数组中的第K个最大元素。
-
数据库查询:在数据库查询中,可能需要找出某个字段值排名第K的记录,这时也需要找出数组中的第K个最大元素。