215. 数组中的第K个最大元素 + 快速排序 + 大根堆
215. 数组中的第K个最大元素
LeetCode-215
另一道类似的第k大元素问题:https://www.cnblogs.com/GarrettWale/p/14386862.html
题目详情
方法一:使用快速排序
package com.walegarrett.interview;
/**
* @Author WaleGarrett
* @Date 2021/2/17 22:24
*/
import java.util.Arrays;
/**
* 题目描述:在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
*/
/**
* 方法一:使用快速排序的思想
*/
public class LeetCode_215 {
public int findKthLargest(int[] nums, int k) {
return quickSort(nums, nums.length-k+1, 0, nums.length -1);
}
/**
* 一趟排序,每一趟返回一个数的确定位置
* @param arr
* @param l
* @param r
* @return
*/
int partition(int[] arr, int l, int r){
int fix = arr[l];//需要确定arr[l]的位置
while(l<r){
while(arr[r] >= fix && l<r)
r--;
if(l<r){
arr[l] = arr[r];
l++;
}
while(arr[l] <= fix && l<r)
l++;
if(l<r){
arr[r] = arr[l];
r--;
}
}
//最后才确定fix的位置
arr[l] = fix;
return l;
}
/**
* 查找最小的k个数
* @param arr
* @param k
* @param l
* @param r
*/
int quickSort(int[] arr, int k, int l, int r){
int index = partition(arr, l, r);
if(index == k-1){
return arr[index];
}else if(index <k-1){//找到的index个数小于k个,需要继续往右半部分递归查找
return quickSort(arr, k, index+1, r);
}else{
return quickSort(arr, k, l, index-1);
}
}
}
方法二:使用大根堆排序--自定义堆
/**
* 方法二:自定义大根堆
*/
class LeetCode_215_2 {
public int findKthLargest(int[] nums, int k) {
int heapSize = nums.length;
createHeap(nums,heapSize);
for(int i=nums.length-1;i>=nums.length-k-1;i--){
swap(i,0,nums);
heapAdjust(0,nums,--heapSize);
}
return nums[0];
}
/**
* 构建大根堆:从非叶子结点开始从下往上构建大根堆
* @param nums
* @param heapSize
*/
void createHeap(int[] nums,int heapSize){
int len = heapSize;
for(int i=len/2; i>=0; i--){
heapAdjust(i, nums,heapSize);
}
}
/**
* 堆调整
* @param root
* @param nums
* @param heapSize
*/
void heapAdjust(int root,int[] nums,int heapSize){
int lr = root*2+1, rr=root*2+2;
int len = heapSize;
int maxIndex = root;
if(lr<len && nums[lr]>nums[maxIndex]){
maxIndex = lr;
}
if(rr<len && nums[rr]>nums[maxIndex]){
maxIndex = rr;
}
if(maxIndex!=root){
swap(root,maxIndex,nums);
heapAdjust(maxIndex,nums,heapSize);
}
}
void swap(int i, int j, int[] nums){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
方法四:小顶堆
除了自己手撸堆排序,我们还可以使用java自带的优先队列,它也是实现了小顶堆。
class Solution {
public int findKthLargest(int[] nums, int k) {
// 维护一个小根堆
PriorityQueue<Integer> que = new PriorityQueue<>();
for(int num : nums){
if(k > 0){
que.offer(num);
k--;
}else{
if(que.peek() < num){
que.poll();
que.offer(num);
}
}
}
return que.peek();
}
}
Either Excellent or Rusty