在数组中找到第k大的元素
样例
给出数组 [9,3,2,4,8]
,第三大的元素是 4
给出数组 [1,2,3,4,5]
,第一大的元素是 5
,第二大的元素是 4
,第三大的元素是 3
,以此类推
挑战
要求时间复杂度为O(n),空间复杂度为O(1)
注意事项
你可以交换数组中的元素的位置
解题思路1:
看到找第K大的元素,第一反应是使用优先队列。时间复杂度为O(nlogn),空间复杂度是O(n)。
public class Solution {
/**
* @param n: An integer
* @param nums: An array
* @return: the Kth largest element
*/
public int kthLargestElement(int n, int[] nums) {
// write your code here
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int i=0 ; i<nums.length ; i++){
queue.add(nums[i]);
}
int k = nums.length - n;
while((k--) != 0){
queue.poll();
}
return queue.peek();
}
}
解题思路2:
要达到挑战的要求,就得用快排的思路,因为快排中的partition操作是找到某个元素它应该在数组中的位置,而第k大的元素就是描述了此元素他应该在的位置,所以我们对快排做一些改变即可达成目的。
public class Solution {
/**
* @param n: An integer
* @param nums: An array
* @return: the Kth largest element
*/
public int kthLargestElement(int n, int[] nums) {
// write your code here
int k = nums.length - n;
return help(k , nums , 0 , nums.length-1);
}
public static int help(int k , int[] nums , int l , int r){
int p = partition(nums , l , r);
if(p == k)
return nums[p];
else if(p < k)
return help(k , nums , p+1 , r);
else
return help(k , nums , l , p-1);
}
public static int partition(int[] nums , int l , int r){
//防止在近乎有序的数组中,partition分割极度不平衡,可使v元素随机化选取
swap(nums , l , (int)(Math.random()*(r-l+1))+l);
int v = nums[l];
int j = l;
for(int i = j+1 ; i<=r ; i++){
if(nums[i] < v){
swap(nums , i , ++j);
}
}
swap(nums , l , j);
return j;
}
private static void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}