题目描述
某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
输入描述:
第1行是整数n,表示自然数的个数。
第2~n+1行每行一个自然数。
输出描述:
输出m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。
示例1
输入
8
2
4
2
4
5
100
2
100
输出
2 3
4 2
5 1
100 2
备注
40%的数据满足:1 ≤ n ≤ 1000
80%的数据满足:1 ≤ n ≤ 50000
100%的数据满足:1 ≤ n ≤ 200000,每个数均不超过1500000000(1.5*109)
解答
这道题我的思路和别人不太一样,也许比较麻烦,但是思路特别好想。
首先根据输出样例,我们看到每一个数都对应了一个它所对应的出现次数。于是根据这一点,我们可以构建一个结构体:
“int k”代表输入的数,“int c”就是这个数对应的出现次数。这样我们就可以直接把数以及对应的出现次数一起输出,而免去了使用tot计数,而每次循环过后清零的麻烦(但是实际上使用tot计数的方法也有优点:占用内存小,速度会稍微快一点)。
主程序很简单,先将所有的数从小到大排序(满足从小到大输出的要求),之后从头到尾遍历每一个数,如果前一个数和后一个数大小相同,那么就可以将后一个数对应的出现次数,加上前一个数对应的出现次数(次数的初始值定为1, 这个我不用说),同时把前一个数清零。
这样,我们把所有不为零的数依次输出,同时输出对应的出现次数。由于一开始已经排过序,所以输出的数就是从小到大已经排序好的。
话不多说,看代码。(代码可能有些工程风格,同时也有测试输出的调试程序,但是相信大家也都能看懂)
#include <iostream> #include<cstdio> #include<algorithm> const int maxN=1500000; using namespace std; struct node{ int k; int c=1; }a[maxN]; int n; int cmp ( node b, node a){ return b.k<a.k;} void INPUT() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i].k); return; } void work() { sort(a+1,a+n+1,cmp); for (int i=1;i<=n;i++) { if(a[i].k==a[i+1].k) { a[i].k=0; a[i+1].c+=a[i].c; } if(a[i].k!=0) cout<<a[i].k<<" "<<a[i].c<<endl; } return; } int main() { INPUT(); work(); /*for (int i=1;i<=n;i++) cout<<a[i].k<<" "<<endl; //cout << "Hello world!" << endl;*/ return 0; }
来源:奔跑的太阳