试题编号: 201503-2
试题名称: 数字排序
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出。
输入格式
输入的第一行包含一个整数n,表示给定数字的个数。
第二行包含n个整数,相邻的整数之间用一个空格分隔,表示所给定的整数。
输出格式
输出多行,每行包含两个整数,分别表示一个给定的整数和它出现的次数。按出现次数递减的顺序输出。如果两个整数出现的次数一样多,则先输出值较小的,然后输出值较大的。
样例输入
12
5 2 3 3 1 3 4 2 5 2 3 5
样例输出
3 4
2 3
5 3
1 1
4 1
评测用例规模与约定
1 ≤ n ≤ 1000,给出的数都是不超过1000的非负整数。
题解:
我的思路:
使用结构体来记录每个元素出现的次数cnt,最后根据出现次数cnt来排序,
注意:
1.如果cnt相等还要根据元素的值来排序,所以这里还记录了元素的值x。
2.排序的数组大小直接开MAX而不能用n,因为虽然是n个数,但是下标(元素的值)可能会超过n。
巧妙的思路(参考其他博文):
暴力枚举:
因为一个数最多出现1000次,一个数最大也就是1000,那我们直接枚举即可。
第一重循环:按照次数从大到小枚举
第二重循环:按照数的大小从小到大枚举
如果某个数出现的次数等于i,则输出即可,而且也保证了如果出现次数相等,优先输出小的数。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <bitset>
#include <iterator>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double E = exp(1.0);
const int MOD = 1e9+7;
const int MAX = 1e3+5;
int n;
/* */
struct A
{
int x = 0;
int cnt = 0;
}a[MAX];
int cmp(const A a, const A b)
{
if(a.cnt != b.cnt)
{
return a.cnt > b.cnt;
}
else
{
return a.x < b.x;
}
}
/*
int a[MAX];
*/
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while(cin >> n)
{
/* MyCode*/
int x;
for(int i = 0; i < n; i++)
{
cin >> x;
a[x].x = x;
a[x].cnt++;
}
sort(a,a+MAX,cmp);// 排序不能只是a+n,因为比如只有10个数,但是x可能为100
for(int i = 0; i < n && a[i].cnt != 0; i++)
{
cout << a[i].x << " " << a[i].cnt << endl;
}
/* 巧妙的两重循环法
int x;
for(int i = 0; i < n; i++)
{
cin >> x;
a[x]++;
}
for(int i = MAX; i >= 1; i--)// 枚举出现次数(最大为1000次)
{
for(int j = 0; j < MAX; j++)// 枚举所有的数(最大为1000)
{
if(a[j] == i)
{
cout << j << " " << a[j] << endl;
}
}
}*/
}
return 0;
}