215. 数组中的第K个最大元素
【题目】:
【代码】:
方法1:堆排序
class Solution {
public static int findKthLargest(int[] nums, int k) {
int len = nums.length;
int[] a = new int[len + 1];
int i = 1;
for (int j : nums) {
a[i++] = j;
}
//建大顶堆
BuildHeap(a, len);
for (i = len; i > 1; i--) {
a[0] = a[1];
a[1] = a[i];
a[i] = a[0];
if (len - i + 1 == k) {
return a[i];
}
AdjustDown(a, 1, i - 1);
}
return a[len - k + 1];
}
//建堆
static void BuildHeap(int a[], int len) {
for (int i = len / 2; i > 0; i--) {
AdjustDown(a, i, len);
}
}
//向下调整
static void AdjustDown(int a[], int k, int len) {
a[0] = a[k];
for (int i = 2 * k; i <= len; i = i * 2) {
if (i < len && a[i] < a[i + 1]) {
i++;
}
if (a[0] >= a[i])
break;
else {
a[k] = a[i];
k = i;
}
}
a[k] = a[0];
}
}
效果:
方法2:引入小顶堆,时间复杂度 O(NlogK),空间复杂度 O(K)
Java中PriorityQueue可参考:深入理解Java PriorityQueue
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> pq=new PriorityQueue<>();
for(int i: nums){
pq.offer(i);
if(pq.size()>k){
pq.poll();
}
}
return pq.peek();
}
效果:方法很巧妙,但是执行时间还行~
方法3:快排
class Solution {
public int findKthLargest(int[] nums, int k) {
k=nums.length-k;
int low=0, high=nums.length-1;
while(low<high){
int pri=partion(nums, low, high);
if(pri==k){
return nums[k];
}else if(k < pri){
high=pri-1;
}else{
low=pri+1;
}
}
return nums[k];
}
public int partition(int[] a, int low, int high){
swap(a, low, new Random().nextInt(high-low) + low); //随机选取基准(加上这一步执行时间快了好多!)
int pivot=a[low];
while(low<high){
while(low<high && a[high]>=pivot){
high--;
}
a[low]=a[high];
while(low<high && a[low]<=pivot){
low++;
}
a[high]=a[low];
}
a[low]=pivot;
return low;
}
}
效果:
以第一个数为基准时:
随机选取基准时:
方法4:插入排序
public int findKthLargest(int[] nums, int k) {
// 插入排序,按照从大到小进行排序
int length = nums.length;
for (int i = 1; i < length; i++) {
// 待插入数据
int cur = nums[i];
int j = i - 1;
while (j >= 0 && nums[j] < cur) {
nums[j + 1] = nums[j];
j--;
}
nums[j + 1] = cur;
}
return nums[k - 1];
}
效果: