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.
Java Solution 1 – Sorting
public int findKthLargest(int[] nums, int k) { Arrays.sort(nums); return nums[nums.length-k]; } |
Time is O(nlog(n)). The problem of this solution is that sorting all elements is not necessary and is a overkill for getting just one element.
Java Solution 2 – Heap
We can use a min heap to solve this problem. The heap stores the top k largest elements.The top of the heap is the Kth Largest element and all other elements are greater than the heap top. Whenever the size is greater than k, delete the min. Time complexity is O(nlog(k)). Space complexity is O(k) for storing the top k numbers.
public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> q = new PriorityQueue<Integer>(k); for(int i: nums){ q.offer(i); if(q.size()>k){ q.poll(); } } return q.peek(); } |
Time complexity of n*log(k) is an improvement to Solution 1. However, this solution requires O(k) space complexity and it is also maintained k-element heap.
Java Solution 3 – Quick Sort
This problem can also be solved by using a similar method like quicksort.
public int findKthLargest(int[] nums, int k) { if (k < 1 || nums == null) { return 0; } return getKth(nums.length - k +1, nums, 0, nums.length - 1); } public int getKth(int k, int[] nums, int start, int end) { int pivot = nums[end]; int left = start; int right = end; while (true) { while (nums[left] < pivot && left < right) { left++; } while (nums[right] >= pivot && right > left) { right--; } if (left == right) { break; } swap(nums, left, right); } swap(nums, left, end); if (k == left + 1) { return pivot; } else if (k < left + 1) { return getKth(k, nums, start, left - 1); } else { return getKth(k, nums, left + 1, end); } } public void swap(int[] nums, int n1, int n2) { int tmp = nums[n1]; nums[n1] = nums[n2]; nums[n2] = tmp; } |
Average case time is O(n), worst case time is O(n^2).
Reference:
http://www.cs.yale.edu/homes/aspnes/pinewiki/QuickSelect.html
I was talking about Java Solution 2 Using Heap
Reference needed.
PriorityQueue is by default the maxHeap, it should be minHeap
PriorityQueue minHeap = new PriorityQueue(new Comparator() {
@Override
public int compare(Integer a, Integer b) {
return a – b;
}
});
agree. current implementation is for k-th SMALLEST element in array
No it does not: http://stackoverflow.com/questions/9755721/how-can-building-a-heap-be-on-time-complexity
Build max heap with the contents of the array actually takes
O(n * log(n))
.You can solve this problem in O(N) average complexity using the Order statistics algorithm http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-introduction-to-algorithms-sma-5503-fall-2005/video-lectures/lecture-6-order-statistics-median/lec6.pdf
A guaranteed processing O(K log N) and space O(N) solution is:
1- Build max heap with the contents of the array O(N)
2- remove first K elements (K log N)
3- the Kth max is the last removed element in step 2
Also, just a note: the average case time for the given solution (quickselect) is O(n) _only_ when using randomized pivot selection (just like in quick sort), not for the naive selection logic used in the example.
i think original post is correct, it should be k since the calculation is always based on the indexs of nums,
for the recursive code above, the last condition(k > left + 1), the 1st parameter for recursive function should be (k – left – 1)
The heading is wrong, it finds the kth smallest element. Not the kth largest element
An O(NlogK) solution applying MinHeap:
public static int solution_1(int[] arr, int k) throws Exception {
//parameter check
assert (arr != null && arr.length > 0 && k > 0 && k <= arr.length);
MinHeap minHeap = new MinHeap(k);
for(int i = 0; i < arr.length; ++i) {
if(minHeap.getCurSize() < k) minHeap.insert(arr[i]);
else if(minHeap.peek() < arr[i]) {
minHeap.getHeapArray()[0] = arr[i];
minHeap.siftDown(0);
}
}
return minHeap.removeMin();
}
public static void main(String[] args) throws Exception {
System.out.println(solution_1(new int[]{3,2,1,5,6,4}, 1));
System.out.println(solution_1(new int[]{3,2,1,5,6,4}, 2));
System.out.println(solution_1(new int[]{3,2,1,5,6,4}, 3));
System.out.println(solution_1(new int[]{3,2,1,5,6,4}, 4));
System.out.println(solution_1(new int[]{3,2,1,5,6,4}, 5));
System.out.println(solution_1(new int[]{3,2,1,5,6,4}, 6));
System.out.println(solution_1(new int[]{4,6,5,1,2,3}, 1));
System.out.println(solution_1(new int[]{4,6,5,1,2,3}, 2));
System.out.println(solution_1(new int[]{4,6,5,1,2,3}, 3));
System.out.println(solution_1(new int[]{4,6,5,1,2,3}, 4));
System.out.println(solution_1(new int[]{4,6,5,1,2,3}, 5));
System.out.println(solution_1(new int[]{4,6,5,1,2,3}, 6));
}