题目
牛客网-查找第k小数
查找一个数组的第K小的数,注意同样大小算一样大。 如 2 1 3 4 5 2 第三小数为3。
题解1
条件反射想到了快排,如果数组没有重复元素的话,直接快排然后判断枢轴元素是不是第k个就好了,王道书上就有例题
但是这道题是有重复元素的,需要去重才能找到真正第k小而不是排在第k位的
到这里还没完,还有一个问题是排序和去重应该先做哪一步?答案是应该先排序再去重,目的是降低时间复杂度或者空间复杂度,因为排序之后重复元素必然是相邻的,因此采用有序数组去重的方法即可,时间复杂度只需O(n)(王道上有原题)
无序 数组去重的方法需要利用辅助数组,代码如下:
/*无序数组去重*/
int main()
{
/*输入*/
int n,a[100];
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
int temp[100];
/*去重*/
int m=0;//记录temp中元素个数
for(int i=0;i<n;i++)
{
int j=0;
for(;j<m;j++)
{
if(a[i]==temp[j])
break;
}
//到头了都没找到和a[i]相等的元素
//说明a[i]不是重复元素
//把a[i]加入temp里
if(j==m)
{
temp[m++]=a[i];
}
}
//输出
for(int i=0;i<m;i++)
cout<<temp[i]<<" ";
}
所以如果硬要先去重再排序的话,代码长这样:
#include<iostream>
#include<cstring>
using namespace std;
// 去重,采用辅助数组
int del(int *a,int n)
{
int temp[1001];
int m=0;//记录temp中元素个数
for(int i=0;i<n;i++)
{
int j=0;
for(;j<m;j++)
{
if(a[i]==temp[j])
break;
}
//到头了都没找到和a[i]相等的元素
//说明a[i]不是重复元素
//把a[i]加入temp里
if(j==m)
{
temp[m++]=a[i];
}
}
memcpy(a,temp,sizeof(temp));//数组赋值的方法,注意一定不能直接赋值
return m;
}
// 快排找第k小(王道上有原题)
int quickSort(int low,int high,int k,int *a)
{
int alow=low;
int ahigh=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;
//下标为low的元素其实是第(low+1)个
if(low==k-1)
return pivot;
else if(low>k-1)
return quickSort(alow, low-1, k,a);
else
return quickSort(low+1, ahigh, k, a);
}
int main()
{
int n,k,a[1001];
while(cin>>n)
{
for(int i=0;i<n;i++)
cin>>a[i];
cin>>k;
n=del(a,n);//去重,返回新的数组的元素个数
int res=quickSort(0,n-1,k,a);//快排找第k小
cout<<res;
}
}
改了好多遍才过的。。。还是太久没打代码生疏了,有的用法都忘记了
题解2
当然用库函数更简单了,但是感觉就没有练习的必要了,代码如下:大致思想是先排序(sort函数)后去重(unique函数),返回第k个元素
#include<iostream>
#include <algorithm>
using namespace std;
int main()
{
int n,k,a[1001];
while(cin>>n)
{
for(int i=0;i<n;i++)
cin>>a[i];
cin>>k;
/*sort+unique几乎可以算是数组去重的一个模板了,用的蛮多的,应该记下来*/
sort(a,a+n);//排序
unique(a,a+n);//去重
cout<<a[k-1];//注意第k个元素的下标是k-1
}
}
提交了几次平均时间和内存跟题解1也差不多。。。
这篇鸽了三天,主要是自己太菜了,这个代码改了好多遍都没过,还有最近课设+毕设比较忙,老把代码拖到最后做不完,现在稍微轻松一点了,一定争取赶上进度