变种快排:寻找最大的前K个数

寻找n个数中的最大前K个数,一般可以想到选择排序或者堆排序,这里介绍一种利用快排思想的方法。

快排每一轮是把一组数据分成三部分,小于基准数的数,基准数,大于等于基准数的数。可以想到当大于等于基准数的数量等于K时这一部分就是所求答案。我们可以使用快排降序排序思想,因为快排每次会确定一个基准数的最终位置,每次得到基准数的下标(下标从0开始)后我们将之与k-1比较,当等于时,说明基准数和基准数左边的数是前K大的数(注意这些数并不是降序序列)。当小于时,说明此时基准以及左侧的数不够K个,但可以确定基准数以及基准数左侧的数肯定在这K个数中,所以不必管基准数以及他左侧的数,对右侧的数再进行上述操作,直到得到答案。当大于时,说明基准数和基准数左侧的数多于k个,对左侧的数进行上述操作,直到得到答案。平均时间复杂度比快排快一倍O(nlogn),最坏时间复杂度为O(n^2).

代码

#include
#include
#include
#include

using namespace std;

void Qs(int low,int high,vector<int>&nums,int k)
{
	int i=low,j=high,temp=nums[low];
	while(i<j){
		while(i<j&&nums[j]<temp){
			j--;
		}
		nums[i]=nums[j];
		while(i<j&&nums[i]>=temp){
			i++;
		}
		nums[j]=nums[i];
	}
	nums[i]=temp;
	if(j==k-1){
		return ;
	}else{
		if(j>=k){
			Qs(low,j-1,nums,k);
		}else{
			Qs(i+1,high,nums,k);
		}
	}
}

int main()
{
	int n,k,x;
	vector<int>nums;
	nums.clear();
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++){
		scanf("%d",&x);
		nums.push_back(x);
	}
	Qs(0,n-1,nums,k);
	for(int i=0;i<k;i++){
		if(i!=0){
			printf(" "); 
		}
		printf("%d",nums[i]);
	}
	return 0;
}

你可能感兴趣的:(面试算法,算法)