1. 题目

考察点
这道题的考察点是数组,排序,堆和快速选择算法。
- 你需要知道如何对数组进行排序,以及不同的排序算法的时间和空间复杂度。
- 你需要知道如何使用堆来维护一个有序的集合,以及如何利用堆的性质来快速找到第k个最大的元素。
- 你需要知道如何使用快速选择算法来在平均O(n)的时间内找到第k个最大的元素,以及如何处理数组中的重复元素和边界情况。
这道题是一个经典的面试问题,可以帮助你提高你的编程能力和逻辑思维。
2. 解法
有多种方法可以用Java实现,例如:
- 使用Arrays.sort()方法对数组进行排序,然后返回数组的第nums.length - k个元素。
- 使用PriorityQueue类创建一个最大堆,将数组中的所有元素加入堆中,然后弹出k-1个元素,最后返回堆顶元素。
- 使用快速选择算法,根据一个随机的基准元素将数组分为两部分,如果基准元素的位置等于nums.length - k,则返回该元素;如果小于,则在右边部分继续查找;如果大于,则在左边部分继续查找。
// 方法一:排序
public class Solution1 {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}
// 方法二:最大堆
public class Solution2 {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
for (int i : nums) {
maxHeap.offer(i);
}
while (k-- > 1) {
maxHeap.poll();
}
return maxHeap.poll();
}
}
// 方法三:快速选择
public class Solution3 {
public int findKthLargest(int[] nums, int k) {
int start = 0;
int end = nums.length - 1;
int index = nums.length - k;
while (start < end) {
int pivot = partition(nums, start, end);
if (pivot < index) {
start = pivot + 1;
} else if (pivot > index) {
end = pivot - 1;
} else {
return nums[pivot];
}
}
return nums[start];
}
int partition(int[] nums, int start, int end) {
int pivot = start;
while (start <= end) {
while (start <= end && nums[start] <= nums[pivot]) {
start++;
}
while (start <= end && nums[end] > nums[pivot]) {
end--;
}
if (start > end) {
break;
}
swap(nums, start, end);
}
swap(nums, end, pivot);
return end;
}
void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
浙公网安备 33010602011771号