题目描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210427155203622.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Zpc2hlcmlzaA==,size_16,color_FFFFFF,t_70)
// 215. 数组中的第K个最大元素
// 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的
// 第 k 个最大的元素,而不是第 k 个不同的元素。
题解
// 毫无意义的解(但效果不错)
// 执行用时:2 ms, 在所有 Java 提交中击败了91.08%的用户
// 内存消耗:38.6 MB, 在所有 Java 提交中击败了82.18%的用户
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}
// 最小堆法
// 傻瓜方法,跟【剑指offer】40. 最小的k个数 有点像,不过还不是很一样。
// 要找最大的k个数,就创建大小为k的最小堆(用优先队列模拟,默认堆顶是最小值)
// ,而且最小堆minHeap中只存储nums中最大的k个数。那么nums中的最大的
// k个数都在minHeap中了,而且minHeap是最小堆,所以堆顶元素就是第k大的数。
//
// 具体实现:遍历nums所有元素,如果minHeap为空,或者minHeap的长度不足k,则
// 直接将遍历元素num存入minHeap中,如果minHeap长度达到k,则已经定义为装满,
// 之后再遍历到的元素num将和minHeap的堆顶元素对比,如果num大于堆顶元素
// 那将minHeap堆顶元素弹出,将num存入minHeap。如此循环,可以保证,
// 在遍历过nums的所有元素之后,minHeap装的k个元素是nums中最大的k个数,
// 并且堆顶元素就是第k大元素。
//
// 不清楚的可以打印出堆的情况看看 System.out.println(minHeap);
// [3,2,1,5,6,4] 和 k = 2
// 执行用时:8 ms, 在所有 Java 提交中击败了37.70%的用户
// 内存消耗:38.5 MB, 在所有 Java 提交中击败了93.01%的用户
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
for (int num: nums) {
if (minHeap.isEmpty())
minHeap.add(num);
else if (minHeap.size() < k)
minHeap.add(num);
else if (minHeap.size() >= k && num > minHeap.peek()) {
minHeap.poll();
minHeap.add(num);
}
}
return minHeap.peek();
}
}
// 简化一下
// 执行用时:5 ms, 在所有 Java 提交中击败了54.12%的用户
// 内存消耗:38.7 MB, 在所有 Java 提交中击败了66.71%的用户
import java.util.PriorityQueue;
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int num: nums) {
if (minHeap.size() < k || num > minHeap.peek())
minHeap.add(num);
while (minHeap.size() > k)
minHeap.remove(minHeap.peek());
// System.out.println(minHeap);
}
return minHeap.peek();
}
}
// 快排选择法
// 将nums.length - k赋给kth,我们不需要所有nums元素进行排序,
// 只需要选择nums前nums.length - k个元素进行排序,然后取到nums.length - k
// 即可。将nums.length - k记为kth。直接把快排的partition写进来,swap写进来,
// 重写快排递归函数quickSortSelect,partition求得的mid,再次递归之前进行判定
// ,如果mid和kth相等,则直接将arr[mid]赋值给res,之后结束递归,返回结果res。
// 如果mid小于kth,则mid还需要右移,递归调用,令left为mid+1,
// 如果mid大于等于kth,则说明mid还需要左移,递归调用,令right为mid-1。
// 当mid等于kth时,排序完成,令res等于arr[mid]。直接返回res即可。
//
// 执行用时:10 ms, 在所有 Java 提交中击败了29.98%的用户
// 内存消耗:38.9 MB, 在所有 Java 提交中击败了29.90%的用户
public class Solution {
int kth;
int res = 0;
public int findKthLargest(int[] nums, int k) {
this.kth = nums.length - k;
quickSortSelect(nums, 0, nums.length - 1);
return res;
}
private void quickSortSelect(int[] arr, int left, int right) {
int mid = partition(arr, left, right);
if (mid == kth)
res = arr[mid];
else if (mid < kth)
quickSortSelect(arr, mid + 1, right);
else
quickSortSelect(arr, left, mid - 1);
return;
}
private static int partition(int[] arr, int left, int right) {
int pivot = arr[left];
int l = left;
int r = right;
while (l < r) {
while (l <= r && arr[l] <= pivot)
l++;
while (l <= r && arr[r] >= pivot)
r--;
if (l < r)
swap(arr, l, r);
}
arr[left] = arr[r];
arr[r] = pivot;
return r;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// 减少递归的修改
// 执行用时:10 ms, 在所有 Java 提交中击败了29.98%的用户
// 内存消耗:38.6 MB, 在所有 Java 提交中击败了78.18%的用户
public class Solution {
int kth;
int res = 0;
public int findKthLargest(int[] nums, int k) {
this.kth = nums.length - k;
quickSortSelect(nums, 0, nums.length - 1);
return res;
}
private void quickSortSelect(int[] arr, int left, int right) {
while (true) {
int mid = partition(arr, left, right);
if (mid == kth) {
res = arr[mid];
break;
}
else if (mid < kth)
left = mid + 1;
else
right = mid - 1;
}
}
private static int partition(int[] arr, int left, int right) {
int pivot = arr[left];
int l = left;
int r = right;
while (l < r) {
while (l <= r && arr[l] <= pivot)
l++;
while (l <= r && arr[r] >= pivot)
r--;
if (l < r)
swap(arr, l, r);
}
arr[left] = arr[r];
arr[r] = pivot;
return r;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}