问题描述:
找到未排序数组中的第k个最大元素。注意,它是排序顺序中的第k个最大元素,而不是第k个不同元素。
解题思路:
可以直接调用sort函数来给数组排序,从而得到第k个最大元素。然而实际上,我们并不需要对整个数组进行排序。过程如下:我们可以任取数组中的一个元素,并以它为主元将原来的数组划分为3个部分,第一个部分是大于主元的,第二个部分是等于主元的,第三个部分是小于主元的。当然,这三个部分不一定有序。然后,我们判断第k个最大元素应该在哪个部分中,然后对那个部分继续这个过程。
将上述算法改写成代码的时候,比较难的部分是如何将数组划分为3个部分。下面的代码和快排的代码很像,思路也是如出一辙。先将数组分为>pivot和<=pivot两个部分,然后再从尾部开始进行一次划分,将<pivot的元素都放在靠近数组尾部的位置。这样一来,数组就被划分为了>pivot,=pivot,<pivot三个部分。
源代码如下:
class Solution {
public:
int helpFindKthLargest(vector<int>& nums, int k,int begin,intend)
{
int last_big=begin;
int pivot=nums[(begin+end)/2];
int c1=0;
swap(nums[begin],nums[(begin+end)/2]);
for(int i=begin+1;i<=end;i++)
{
if(nums[i]>pivot)
{
swap(nums[i],nums[last_big+1]);
last_big++;
c1++;
}
}
swap(nums[begin],nums[last_big]);
int last_small=end;
int c3=0;
swap(nums[end],nums[last_big]);
for(int i=last_small-1;i>=begin;i--)
{
if(nums[i]<pivot)
{
swap(nums[i],nums[last_small-1]);
last_small--;
c3++;
}
}
swap(nums[end],nums[last_small]);
int c2=end-begin+1-c1-c3;
if(k<=c1) return helpFindKthLargest(nums,k,begin,c1+begin-1);
else if(k<=(c1+c2)) return pivot;
else return helpFindKthLargest(nums,k-c1-c2,end+1-c3,end);
}
int findKthLargest(vector<int>& nums,int k)
{
return helpFindKthLargest(nums,k,0,nums.size()-1);
}
};