https://leetcode.com/problems/kth-largest-element-in-an-array/
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.
**input: **an unsorted array, an integer k
output: return an integer, which is the kth largest in the given array, including duplicates
corner: when the array is null, or its length is less than k, there is no such element
The primitive idea is to sort the array, and count the kth element, if we use merge sort
, it will take O(n logn), plus O(k) to count.
Or we can optimize that we just sort the largest k elements, ignoring the remain n-k elements. It will raise the Heap
structure, since it's fast to find the largest element.
So, we scan from left to right in the array, first put k elements into a heap to heapify
. Time is O(k)
This heap is a minHeap
where its top is the smallest.
Every time we scan an element in the array, we compare it with the top of the heap.
If it's smaller than or equal to top, we keep moving on.
If it's larger than top, we pop the top, and put it in the top, and main the heap to be a minHeap. Time is O(logk)
After we scanned all the elements in the array, we just need to pop the top, which is the right largest one. Need to compare n - k
times.
Finally, time complexity is O((n - k)logk + k)
space is O(k)
public class Solution {
public int findKthLargest(int[] nums, int k){
if ( nums == null || nums.length < k ){
return Integer.MIN_VALUE;
}
//method: maintain a min heap with size k
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(k, new MyComparator());
//1.add first k elements
for ( int i = 0; i < k; i++ ){
minHeap.offer(nums[i]);
}
//2.compare remain elements, add
for ( int i = k; i < nums.length; i++ ){
if ( nums[i] > minHeap.peek() ){
minHeap.poll();
minHeap.offer(nums[i]);
}
}
return minHeap.poll();
}
class MyComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2){
if ( o1.equals(o2) ){
return 0;
}else{
//from small to large, minHeap
return o1 - o2;
}
}
}