求第k小数

求第k小数,无非就是考查排序,请参考我最新的博文吧求第k小数----直接使用priority_queue,在网上看到许多使用快排来求第k小数都是认为第k小就是排好序数组中第k个元素,但是如果数组中有相同的元素呢,例如(1,2,2,2,3,5),认为第三小是3还是2呢?我刷题时遇到的是认为是3。没有想到什么好办法,先排序再找第k小,直接写俩排序算法好了,一个冒泡一个快排,但个人认为堆排序是最好的,可以维护一个大小为k的大顶堆,每次取到最大的元素,如果当前元素小于堆顶元素(最大)则放入堆中,最终堆中最底部的元素就是第k小数。

冒泡排序没什么好说的吧,直接附上代码好了,没有用优化的冒泡排序,优化的也就是加一个判断,之所以写出来这个是因为发现在刷题时这种方法也能pass。

#include<iostream>
using namespace std;
int main(){
	int n;			//n为元素数目 
	int k;			//k代表要查找的元素,如要找第三小,k=3 
	cin>>n;
	int a[n];		//数组a中存放的就是要排序的元素 
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	cin>>k;
	for(int i=0;i<n;i++){			//很暴力的冒泡排序,不多说了 
		for(int j=n-1;j>=i+1;j--){
			if(a[j]<a[j-1]){
				int temp=a[j];
				a[j]=a[j-1];
				a[j-1]=temp;
			}
		}
	}
	int index=0,i=0;
	while(index!=k){		        //对排好序后的数组查找第k小的元素 
		if(a[i]!=a[++i]){
			index++;
		}
	}
	cout<<a[i-1]<<endl; 
}

还是用点有技术含量的算法吧,利用快排来求第k小元素,这里同样注意数组中可能有相同的元素

#include<iostream>
using namespace std;
int Partition(int*a,int low,int high){
	int pivot=a[low];
	while(low<high){
		while(low<high&&a[high]>=pivot)--high;
		a[low]=a[high];			//比枢轴小的移动到左边 
		while(low<high&&a[low]<=pivot)++low;
		a[high]=a[low];			//比枢轴大的移动到右边 
	}
	a[low]=pivot;				//找好枢轴位置 
	return low;				//返回枢轴位置 
}
void quickSort(int*a,int low,int high){         //快排算法
	if(low<high){
		int dir=Partition(a,low,high);
		quickSort(a,low,dir-1);
		quickSort(a,dir+1,high);
	}
}
int findK(int*a,int k){                         //对排好序后的数组查找第k小的元素
	int index=0,i=0;
	while(index!=k){			 
		if(a[i]!=a[++i]){
			index++;
		}
	}
	return a[i-1];
}
int main(){
	int n;			//n为元素数目 
	int k;			//k代表要查找的元素,如要找第三小,k=3 
	cin>>n;
	int a[n];		//数组a中存放的就是要排序的元素 
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	cin>>k;
	quickSort(a,0,n-1);
	cout<<findK(a,k);
}

我的思路很简单就是先排序再求第k小,但是如果用堆排序的话应该能有效减小规模,因为要求的是第k小,并不需要把所有数组都排序,堆排使用空间还比较小。

输入:

6

2 1 3 5 2 2

3

输出:

3

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值