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; } }