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.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
// method 1: O(nlogn)
public int findKthLargest1(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
// method 2: quick select: standard recursive version
public int findKthLargest2(int[] nums, int k) {
quickSelect(nums, k, 0, nums.length - 1);
return nums[nums.length - k];
}
private static final int CUTOFF = 10;
public void quickSelect(int[] nums, int k, int left, int right) {
if (left + CUTOFF <= right) {
int pivot = median3(nums, left, right);
int i = left, j = right - 1;
while (true) {
while(nums[++i] < pivot) {}
while(nums[--j] > pivot) {}
if (i < j) {
swap(nums, i, j);
} else {
break;
}
}
swap(nums, i, right - 1);
if (nums.length - k < i)
quickSelect(nums, left, i - 1, k);
else if (nums.length - k > i)
quickSelect(nums, i + 1, right, k);
} else {
insertionSort(nums, left, right);
}
}
private int median3(int[] nums, int left, int right) {
int mid = (left + right) / 2;
if (nums[mid] < nums[left])
swap(nums, left, mid);
if (nums[mid] > nums[right])
swap(nums, mid, right);
if (nums[mid] < nums[left])
swap(nums, left, mid);
swap(nums, mid, right - 1);
return nums[right - 1];
}
private void swap(int[] nums, int p1, int p2) {
int tmp = nums[p1];
nums[p1] = nums[p2];
nums[p2] = tmp;
}
private void insertionSort(int[] nums, int left, int right) {
for (int i = left + 1; i <= right; i++) {
if (nums[i] < nums[i - 1]) {
int tmp = nums[i];
int j = i - 1;
for (; j >= 0 && tmp < nums[j]; j--) {
nums[j + 1] = nums[j];
}
nums[j + 1] = tmp;
}
}
}