【华为机试真题 C++】奥运会排行榜-100

题目描述

2012伦敦奥运会即将到来,大家都非常关注奖牌榜的情况,现在我们假设奖牌榜的排名规则如下:
1,首先,gold medal 数量多的排在前面;
2,其次,sliver medal 数量多的排在前面;
3,然后,bronze medal 数量多的排在前面;
4,若以上三个条件 仍无法区分名次,则以国家名称的字典序排定。

我们假设国家名称不超过20个字符,各种奖牌不超过100,切大于等于0。

输入描述

第一行输入一个整数N(0<N<21),代表国家数量;
然后接下来的N行,每行包含一个字符串Namei表示每个国家的名称,和三个整数Gi、Si、Bi表示每个获得的gold medal、silver medal、bronze medal的数量,以空格隔开,如(China 51 20 21),具体见样例输入。

输出描述

输出奖牌榜的依次顺序,只输出国家名称,各占一行,具体见样例输出。

测试用例

示例1:

输入

3
China 51 20 21
American 50 1 1 
Japan 0 0 0

输出

China
American 
Japan

示例2:

输入

4
China 51 20 21
American 52 1 1 
Japan 51 22 20
Austrila 51 20 21

输出

American
Japan
Austrila
China

解题思路

本题属于典型的自定义排序类的问题。

本题在解题思路上与【Easy】找最小数-100如出一辙,唯一的区别在于本题要求输出结果为所有排序对象中指定字段的值:输出奖牌榜的依次顺序,只输出国家名称,各占一行,格式要符合题目的输出要求即可。

我们以这组测试用例为例,分析下多轮排序比较的过程:

4
China 51 20 21
American 52 1 1 
Japan 51 22 20
Austrila 51 20 21

在这里插入图片描述

这里需要特别说明的是:

  • 要点1:金牌,银牌,铜牌数都是按照数值类型从大到小进行排序;
  • 要点2:当金牌,银牌,铜牌都相同时,则需要按照国家名称字符串类型按照从小到大的字典序进行排序。

这里比较容易忽视的是要点2,有的同学可能依然按照字符串的从大到小的顺序进行排序,有可能会无法通过全部的测试用例哦。

示例代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

using namespace std;

class Record {
public:
    /**
     * 国家名称
     */
    string m_Country;

    /**
     * 金牌
     */
    int m_Gi;

    /**
    * 银牌
    */
    int m_Si;

    /**
    * 铜牌
    */
    int m_Bi;


    Record(const string &mCountry, int mGi, int mSi, int mBi) : m_Country(mCountry), m_Gi(mGi), m_Si(mSi), m_Bi(mBi) {}

};

bool myCompare(Record &record1, Record &record2) {
    if (record1.m_Gi != record2.m_Gi) {
        // 优先按照金牌数由大到小进行排序
        return record1.m_Gi > record2.m_Gi;
    } else {
        // 当金牌数相同时,接着按照银牌数由大到小排序
        if (record1.m_Si != record2.m_Si) {
            return record1.m_Si > record2.m_Si;
        } else if (record1.m_Bi != record2.m_Bi) {
            return record1.m_Bi > record2.m_Bi;
        } else {
            string country1 = record1.m_Country;
            transform(country1.begin(), country1.end(), country1.end(), ::tolower);
            string country2 = record2.m_Country;
            transform(country2.begin(), country2.end(), country2.end(), ::tolower);

            return country1.compare(country2);
        }
    }
}

void myPrint(const Record &record) {
    cout << record.m_Country << endl;
}

int main() {
    int n;
    cin >> n;
    vector<Record> v;
    v.reserve(n);

    for (int i = 0; i < n; ++i) {
        string country;
        int gold, silver, copper;
        cin >> country >> gold >> silver >> copper;
        Record record(country, gold, silver, copper);
        v.push_back(record);
    }

    // 自定义排序
    sort(v.begin(), v.end(), myCompare);

    // 输出
    for_each(v.begin(), v.end(), myPrint);

    return 0;
}

总结

  • 分值:100分
  • 难度:Easy
  • 考点:多关键字排序(自定义排序)

这一类自定义排序题目的一般解题思路为:

  1. 输入数据获取,构造自定义排序对象。
  2. 根据题目中要求的字段比较逻辑,覆写比较方法compareTo().
  3. 执行自定义对象的排序操作。
  4. 按照要求将排序后的结果中制定字段进行输出。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GeekerLou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值