寻找第k大-笔记
- 题目提示使用快速排序的思想找到一个数组中第k大的数。
- 思路:
- 快排思想:使用快排的思想,就是将数组按照基准值划分为左右两边,左边大于基准,先进行一次快排,基准防止的位置为p,将大于基准的值放在前半部分,小于基准的值放在后半部分。大于基准的值有p-left个。所以此时如果p-left+1==k表示此时基准就是第k大的数。如果p-left+1 < k说明第k大在后半段(此时要找后半段中第k-(p-left+1))大的值,如果p-left+1 > k则说明第k大在前半段。但是这代码在牛客上超时了。
- 使用堆排序,只交换k次堆顶和末尾元素,然后返回第k大的元素。
代码
class Solution {
public:
int findpivot(vector<int> &nums,int left,int right){
int i=left,j=right;
int pivot=nums[left];
while(left<right){
while(left<right && nums[right]<pivot){
right--;
}
nums[left]=nums[right];
while(left<right && nums[left]>=pivot){
left++;
}
nums[right]=nums[left];
}
int res=0;
nums[left]=pivot;
return left;
}
int dofind(vector<int>& nums,int left,int right,int k){
int p=findpivot(nums,left,right);
if(p-left+1==k){
return nums[p];
}
else if(p-left+1>k){
return dofind(nums,left,p-1,k);
}
return dofind(nums,p+1,right,k-(p-left+1));
}
int findKth(vector<int> a, int n, int K) {
int left=0,right=n-1;
return dofind(a,left,right,K);
}
};
class Solution {
public:
void adjust(vector<int>& nums,int start,int last){
int maxchild=2*start+1;
while(maxchild<=last){
if(maxchild+1<=last && nums[maxchild]<=nums[maxchild+1]){
maxchild+=1;
}
if(nums[start]<nums[maxchild]){
swap(nums[start],nums[maxchild]);
start=maxchild;
maxchild=2*start+1;
}
else{
return;
}
}
}
void heapfy(vector<int>& nums){
int n=nums.size()-1;
for(int i=(n-1)/2;i>=0;i--){
adjust(nums,i,n);
}
}
int findKth(vector<int> a, int n, int K) {
n=n-1;
heapfy(a);
for(int i=n;i>=n-K;i--){
swap(a[0],a[i]);
adjust(a,0,i-1);
}
return a[n-K+1];
}
};