题目来源:洛谷
题目描述如下:
学校正在选举学生会成员,有 n(n≤999) 名候选人,每名候选人编号分别从 1 到 nn,现在收集到了 m(m<=2000000) 张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。输入 n 和 m 以及 m 个选票上的数字,求出排序后的选票编号。
示例1:
输入:
5 10
2 5 2 2 5 2 2 2 1 2
输出:
1 2 2 2 2 2 2 2 5 5
这道题目其实很简单,就是一个排序就可以了。比如说直接用C++或其他语言的sort函数即可得到对应的答案。但有没有发现其实数据n并没有用上。
如果使用C语言来进行分析的话,就要考虑在本题中,我具体使用哪个排序算法。常用的十大排序算法,其时间复杂度和空间复杂度均各有特点,并且其适用范围也各有不同。
对于本题,由于数据m可以很大,最大可达2000000,因此对于算法复杂度达到二次方的算法显然不可取。因此,我们只能考虑复杂度为O(N)的算法,又基于数据n最大可达999,因此我们再次选择十分稳定的计数排序算法,不论数据的 变化有多么大,最坏和最好的情况况下,我们的算法时间复杂度均为O(N)。无非是多耗费了一些空间。
再加上本题是一个选举问题,因此在实际情况下,必然有很多数据是重复的。选取 计数排序算法再合适不过了。
以下代码为C的代码。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,m;
int a[2000000];
int b[1000]={0};
int i,j;
//memset(b,0,999);
scanf("%d %d",&m,&n);
for(i=0;i<n;i++)
{scanf("%d",&a[i]);
b[a[i]]++;} //统计每个数出现的次数
for (i=0;i<=m;i++)
{if(b[i]==0)
continue;
while(b[i]!=0){ //对相应数据进行输出,每个数据输出b[i]次
printf("%d ",i);
b[i]--;
}
}
return 0;
}