https://www.jianshu.com/p/b30955885e6d
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.
Approach 1: Priority Queue
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minQ = new PriorityQueue<>(k);
for(int i: nums) {
if(minQ.size() < k) {
minQ.add(i);
continue;
}
if(i<=minQ.peek())
continue;
minQ.remove();
minQ.add(i);
}
return minQ.peek();
}
}
Runtime: 8 ms, faster than 46.78% of Java online submissions for Kth Largest Element in an Array.
Memory Usage: 46.2 MB, less than 5.18% of Java online submissions for Kth Largest Element in an Array.
Approach 2: Quick Select
1. Swap low and high element
class Solution {
public int findKthLargest(int[] nums, int k) {
int index = findKthLargest(nums, 0, nums.length-1, k);
return nums[index];
}
int findKthLargest(int[] nums, int start, int end, int k) {
int pivot = nums[start];
int i=start+1;
int j=end;
int temp;
while(i<=j){
while(i<=j) {
if(nums[i] >= pivot) {
i++;
}
else {
break;
}
}
while(i<=j) {
if(nums[j] <= pivot) {
j--;
}
else {
break;
}
}
if( i < j) {
temp = nums[i] ;
nums[i++] = nums[j];
nums[j--] = temp;
}
}
nums[start] = nums[j];
nums[j] = pivot;
int count = j - start + 1;
if(count == k) return j;
if(count < k) return findKthLargest(nums, j+1, end, k - count);
return findKthLargest(nums, start, j-1, k);
}
}
Runtime: 33 ms, faster than 16.55% of Java online submissions for Kth Largest Element in an Array.
Memory Usage: 47.7 MB, less than 5.18% of Java online submissions for Kth Largest Element in an Array.
Improve performance (16.55% -> 99.39%😄)
shuttle pivot
//int mid = start+ (end -start) /2;
int mid = (int) ((Math.random() * (end - start)) + start);
temp = nums[mid] ;
nums[mid] = nums[start];
nums[start] = temp;
Runtime: 1 ms, faster than 99.39% of Java online submissions for Kth Largest Element in an Array.
Memory Usage: 46.9 MB, less than 5.18% of Java online submissions for Kth Largest Element in an Array.
class Solution {
public int findKthLargest(int[] nums, int k) {
int index = findKthLargest(nums, 0, nums.length-1, k);
return nums[index];
}
int findKthLargest(int[] nums, int start, int end, int k) {
int temp;
//int mid = start+ (end -start) /2;
int mid = (int) ((Math.random() * (end - start)) + start);
temp = nums[mid] ;
nums[mid] = nums[start];
nums[start] = temp;
int pivot = nums[start];
int i=start+1;
int j=end;
while(i<=j){
while(i<=j) {
if(nums[i] >= pivot) {
i++;
}
else {
break;
}
}
while(i<=j) {
if(nums[j] <= pivot) {
j--;
}
else {
break;
}
}
if( i < j) {
temp = nums[i] ;
nums[i++] = nums[j];
nums[j--] = temp;
}
}
nums[start] = nums[j];
nums[j] = pivot;
int count = j - start + 1;
if(count == k) return j;
if(count < k) return findKthLargest(nums, j+1, end, k - count);
return findKthLargest(nums, start, j-1, k);
}
}
2. Repeatly search high and low element respectively
class Solution {
public int findKthLargest(int[] nums, int k) {
int index = findKthLargest(nums, 0, nums.length-1, k);
return nums[index];
}
int findKthLargest(int[] nums, int start, int end, int k) {
int pivot = nums[start];
int i=start;
int j=end;
while(i<j){
while(i<j) {
if(nums[j] <= pivot) {
j--;
}
else {
nums[i++] = nums[j];
break;
}
}
while(i<j) {
if(nums[i] >= pivot) {
i++;
}
else {
nums[j--] = nums[i];
break;
}
}
}
nums[i] = pivot;
int count = i - start + 1;
if(count == k) return i;
if(count < k) return findKthLargest(nums, i+1, end, k - count);
return findKthLargest(nums, start, i-1, k);
}
}
Runtime: 43 ms, faster than 6.17% of Java online submissions for Kth Largest Element in an Array.
Memory Usage: 47.1 MB, less than 5.18% of Java online submissions for Kth Largest Element in an Array.
Improve performance
shuttle pivot as above