Today we have a common problem, finding the kth largest element in an array.
We need to find the kth largest element after sorting the array. And we need to solve the time
in linear time.
Problem definition
Input:
A array of n integers and an integer k (1 ≤ k ≤ n).
Output:
The kth largest element in the array.
Example:
Input: [3, 2, 1, 5, 6, 4], k = 2
Output: 5
Approach
The most common algorithm to solve this problem is quicksort. However,
the time complexity is O(nlogn). That is because quicksort do partition of whole array, and then
recurisively
do partition on the left and right subarray, but size of subarray is decrease in logn times, so
total time complexity
is O(logn). But if we only need to find the kth largest element, we don't need to do the
participating for each subarray. We only
need to do partition on the array we think it contains the kth largest element. Therefore, the time
complexity is O(n), O(n/a),O(n/b)...
(a,b is a constant), so the time complexity for whole array is O(n).
Visualization
So divide the array into two subarray, left subarray contains elements smaller than pivot, right
subarray contains elements greater than pivot. And after division, put pivot back to the middle.
We can see that 4 is the 3rd largest element in the array, and we need to find 2nd largest, it is
in the right
subarray. So we only need to repeat the process, keep finding the 2nd largest element on the
right
subarray.
Processing:
And at this time 5 is the 2nd largest element in the right subarray, which is also the 2nd
largest elements of whole array,
so we can return 5 as the result.
Two situations:
If the problem is as the example, kth elements is in the right subarray, we find the kth element
in right subarray, but if the kth elements is in the left subarray,
assume pivot is the ath largest elements, we need to find the k-a th largest element in left
subarray.
For the previous example, if k=5, process should be as follows:
At this time k is the 1st largest element, so find 2-1=1st largest element in left subarray,
easily get final result 2.
Algorithm implementation:
class Solution {
public int findKthLargest(int[] nums, int k) {
int length = nums.length;
int result = divide(nums,0,length-1,k);
return result;
}
public int divide(int[]nums, int startIndex, int endIndex,int k){
int random = (int) (Math.random() * (endIndex - startIndex + 1)) + startIndex;
if(startIndex==endIndex){
return nums[startIndex];
}
int arrLength=endIndex-startIndex+1;
int x=nums[random];
int temp=nums[random];
nums[random]=nums[endIndex];
nums[endIndex]=temp;
int j=startIndex;
int i=j-1;
for(;jk){
return divide(nums,i+2,endIndex,k);
}
return -1;
}
}