1. 问题分析与解法思路
215题要求我们在未排序的数组中找到第k个最大的元素。这个问题看似简单,但考察了我们对数据结构和算法的理解深度。让我们先分析几种可能的解法思路:
1.1 暴力解法与排序法
最直观的解法是将数组排序后直接取第k个元素。使用Java内置的Arrays.sort()方法,时间复杂度为O(nlogn),空间复杂度为O(1)(如果使用堆排序):
java复制Arrays.sort(nums);
return nums[nums.length - k];
这种方法简单直接,但并不是最优解,因为我们实际上不需要对整个数组进行完全排序。
1.2 快速选择算法
快速选择算法是快速排序的变种,平均时间复杂度为O(n),最坏情况下为O(n²)。其核心思想是每次partition后,根据pivot的位置决定继续处理左半部分还是右半部分:
java复制public int findKthLargest(int[] nums, int k) {
int left = 0, right = nums.length - 1;
while (true) {
int pos = partition(nums, left, right);
if (pos == k - 1) return nums[pos];
if (pos > k - 1) right = pos - 1;
else left = pos + 1;
}
}
private int partition(int[] nums, int left, int right) {
int pivot = nums[left];
int l = left + 1, r = right;
while (l <= r) {
if (nums[l] < pivot && nums[r] > pivot) {
swap(nums, l++, r--);
}
if (nums[l] >= pivot) l++;
if (nums[r] <= pivot) r--;
}
swap(nums, left, r);
return r;
}
注意:快速选择算法虽然平均性能好,但在面试中实现起来容易出错,特别是边界条件的处理。
1.3 堆解法
堆解法是这个问题最优雅的解决方案之一,也是面试中最受青睐的解法。它利用了最小堆(Min-Heap)或最大堆(Max-Heap)的特性:
- 使用最小堆:维护一个大小为k的最小堆,堆顶就是第k大的元素
- 使用最大堆:维护一个大小为n-k+1的最大堆,堆顶也是第k
