中等
给定整数数组 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
快排
import java.util.Random;
class Solution {
Random random = new Random();
/*
* 快排思想,包含分区和递归,最主要的是原地排序和小于划分元素。
* 小于等于不行,因为会导致左边出现和划分元素相等的情况,第K小就达不到了。
* 递归:都小于划分元素就够了,不需要严格有序,所以只需要跳到k所在区间继续划分。
* */
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}
public int quickSelect(int[] nums, int left, int right, int k) {
int partitionIdx = partition(nums, left, right);
if (partitionIdx == k) {
return nums[k];
} else if (partitionIdx < k) {
return quickSelect(nums, partitionIdx + 1, right, k);
} else {
return quickSelect(nums, left, partitionIdx - 1, k);
}
}
public int partition(int[] nums, int left, int right) {
int pivotIndex = left + random.nextInt(right - left + 1);
int pivotValue = nums[pivotIndex];
swap(nums, pivotIndex, right); // 把 pivot 移到末尾
int storeIdx = left;
for (int i = left; i < right; i++) {
if (nums[i] < pivotValue) {
swap(nums, i, storeIdx++);
}
}
swap(nums, storeIdx, right); // 把 pivot 放到最终位置
return storeIdx;
}
public void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
小顶堆
import java.util.Random;
class Solution {
Random random = new Random();
/*
* 小顶堆,要求第K大,那就是只需要维护K个长度的小顶堆,转化为获取该小顶堆的堆顶元素。
* */
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> heap = new PriorityQueue<>();
for(int i=0;i<nums.length;i++){
heap.add(nums[i]);
if(heap.size()>k)
heap.poll();
}
return heap.peek();
}
}