题目地址
题意:就是标题,返回第K大元素
思路:最佳解法时间复杂度可以到O(n),所以我们来考虑下最佳解法。首先很容易想到的是可以用快排排序,然后直接下标取第 k 个数,这样复杂度是 O(logn) 。于是我们在这个的基础上深入,快排的底层就是每次选取一个数作为分界,然后通过交换令左边全是比它大(小)的,右边全是比它小(大)的,然后这个数的位置就被确定了,再递归地从这个位置左边和右边分别做上述事情。然而,这题我们只需要知道第 K 大,所以没有必要让整个数组有序,既然我们在每次递归的时候可以确定某个数的位置,那么如果这个数的位置刚好是 k ,我们就没必要递归下去了,直接获取值,而如果不是 k ,我们也可以选择性的递归,比如当前这个数的位置比 k 大,那么这个数右边的数是什么我们是不关心的,所以只要递归左边就行了。经证明该做法时间复杂度为 O(n) 。
class Solution {
public:
int k;
void q_sort(vector<int>&v,int left,int right)
{
if(left>=right) return;
int index=part_sort(v,left,right);
if(index==k-1) return;
if(index>k-1)
q_sort(v,left,index-1);
else
q_sort(v,index+1,right);
}
int part_sort(vector<int>&v,int left,int right)
{
int &a=v[left];
int &b=v[left+((right-left)>>1)];
int &c=v[right];
if((a-b)*(a-c)<=0) swap(a,v[right]);
else if((b-a)*(b-c)<=0) swap(b,v[right]);
else swap(c,v[right]);
int &key=v[right];
while(left<right)
{
while(left<right&&v[left]>=key)
{
left++;
}
while(left<right&&v[right]<=key)
{
right--;
}
swap(v[left],v[right]);
}
swap(v[left],key);
return left;
}
int findKthLargest(vector<int>& nums, int k) {
this->k=k;
q_sort(nums,0,(int)nums.size()-1);
// for(auto i:nums) cout<<i<<' ';
// puts("");
return nums[k-1];
}
};