求第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