Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.



方法一:Arrays.sort() 排序

class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}


方法二:利用Partition算法

之前写过​​使用Partition算法找数组中位数​​,同理,找第k大的数也可以用Partition算法。

由于我们的目标是找到第K大数,不需要把每一个数都排好序,因此还有优化的空间。除了排序以外,我们还可以用快排中的Partition思想。
首先,随机选取一个数作为分类的标准,比它大的都放在它左边,比它小的都放在它右边。

  • 如果这个数的下标刚好是k ,那么这个数就是第k大的数;
  • 如果这个数的下标小于k,说明第k大的数在它的右边;
  • 如果这个数的下标大于k,说明第k大的数在它的左边 ;

例如:
{3,2,1,5,6,4},从大到小排序后为{6,5,4,3,2,1},第2大的数是5。

  • 5的下标为2,说明5就是第2大的数;
  • 6的下标为1,说明第2大的数在6的右边;
  • 4的下标为3,说明第2大的数在4的左边;

这是一个典型的递归过程~

class Solution {
public int findKthLargest(int[] nums, int k) {
return findKthLargestByPartition(nums, 0, nums.length - 1, k - 1);
}

private static int findKthLargestByPartition(int[] nums, int left, int right, int k) {

// 设置i、j为左右标志位
int i = left, j = right;

// key为分类的标志
int key = nums[left];

while(i < j) {
// j向左走,直到遇见一个比key大的数
while(i < j && nums[j] <= key) {
j--;
}
// 把比key大的数,放在位置i上
if(i < j) {
nums[i] = nums[j];
i++;
}

// i向右走,直到遇见一个比key小的数
while(i < j && nums[i] >= key) {
i++;
}
// 把比key小的数,放在位置j上
if(i < j) {
nums[j] = nums[i];
j--;
}
}

nums[i] = key;

// i小于k,说明第k大的数在nums[i]的右边
if(i < k) {
return findKthLargestByPartition(nums, i + 1, right, k);
}
// i大于k,说明第k大的数在nums[i]的左边
else if(i > k) {
return findKthLargestByPartition(nums, left, i - 1, k);
}

// i等于k ,那么nums[i]就是第k大的数
return nums[i];
}


}

从时间上看,Partition耗时54ms,Arrays.sort()排序耗时4ms

Leetcode 215. Kth Largest Element in an Array_javascript

同理,可以将Partision算法用于 “最小的k个数”