CCP-CSP认证考试 201503-2 数字排序 c/c++题解

题目描述

试题编号: 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值