【多关键字排序专题】C++sort函数自定义排序规则,map、unordered_map按照value排序/自定义排序规则

map按value排序/自定义排序规则

sort不能直接排map,需要把map放入到vector中再对vector排序
方法如下

using PSI = pair<string, int>;

vector<PSI> arr;
unordered_map<string, int> mp;

    for (auto &[k, v] : mp) arr.push_back({k, v});
    sort(arr.begin(), arr.end(), [](PSI a, PSI b) {
    	return a.second < b.second;
    });

例题 字符串重新排序

image

样例1
输入

This is an apple

输出

an is This aelpp 

样例2
输入

My sister is in the house not in the yard

输出

in in eht eht My is not adry ehosu eirsst 

C++代码

#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>

using namespace std;
using PSI = pair<string, int>;

string str;
vector<PSI> arr;
unordered_map<string, int> mp;

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    while (cin >> str)
    {
        sort(str.begin(), str.end());
        mp[str]++;
    }
    for (auto &[k, v] : mp) arr.push_back({k, v});
    sort(arr.begin(), arr.end(),
         [](PSI a, PSI b)
         {
             if (a.second != b.second) return a.second > b.second;
             if (a.first.size() != b.first.size())
                 return a.first.size() < b.first.size();
             return a.first < b.first;
         });
    for (auto &[k, v] : arr)
    {
        if (v == 1) cout << k << ' ';
        else
        {
            for (int i = 0; i < v; i++) cout << k << ' ';
        }
    }
    return 0;
}

优秀学员统计

image
样例1
输入

11
4 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
0 1 7 10
0 1 6 10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
6 10
7 10

输出

10 0 1 7 6

说明:
员工编号范围为0~10,id为10的员工连续打卡30天,排第一, id为0,1,6,7的员工打卡都是两天, id为0,1,7的员工在第一天就打卡, 比id为6的员工早,排在前面,0,1,7按id升序排列, 所以输出[10,0,1,7,6]

样例2
输入

7
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5

输出

0 1 2 3 4

说明:
员工编号范围为0-6,id为0,1, 2, 3, 4,5的员工打卡次数相同,最早开始打卡的时间也一样,所以按id升序返回前5个id

样例3
输入

2
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0 1
0 1

输出

1 0

说明:
只有两名员工参与打卡,按规则排序输出两名员工的id


C++代码

#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;
using PII = pair<int, int>;

const int N = 110;

int n, sum; // sum记录当月打卡的员工数量
int day[N];

struct Node
{
    int id, cnt, fday;
    bool operator<(const Node &t) const
    {
        if (cnt != t.cnt) return cnt > t.cnt;
        if (fday != t.fday) return fday < t.fday;
        return id < t.id;
    }
} node[N];

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 0; i < n; i++) node[i].id = i;
    for (int i = 0; i < 30; i++) cin >> day[i];
    for (int i = 0; i < 30; i++)
    {
        int T = day[i];
        while (T--)
        {
            int x;
            cin >> x;
            if (node[x].cnt == 0) node[x].fday = i, sum++;
            node[x].cnt++;
        }
    }
    sort(node, node + n);
    if (sum >= 5) sum = 5;
    for (int i = 0; i < sum; i++) cout << node[i].id << ' ';
    return 0;
}

练习题

429. 奖学金

重载小于号写法

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 310;

int n;
struct Person
{
    int id, sum, a, b, c;
    bool operator< (const Person& t) const 
    {
        if (sum != t.sum) return sum > t.sum;
        if (a != t.a) return a > t.a;
        return id < t.id;
    }
}q[N];

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++ )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        q[i] = {i, a + b + c, a, b, c};
    }
    
    sort(q + 1, q + n + 1);
    
    for(int i = 1; i <= 5; i ++ )
        cout << q[i].id << ' ' << q[i].sum << endl;
    return 0;
}

自定义比较函数写法

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 310;

int n;
struct Person
{
    int id, sum, a, b, c;
}q[N];

bool cmp(Person &a, Person &b)
{
    if (a.sum != b.sum) return a.sum > b.sum;
    if (a.a != b.a) return a.a > b.a;
    return a.id < b.id;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++ )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        q[i] = {i, a + b + c, a, b, c};
    }
    
    sort(q + 1, q + n + 1, cmp);
    
    for(int i = 1; i <= 5; i ++ )
        cout << q[i].id << ' ' << q[i].sum << endl;
    return 0;
}

字符统计及重排

image

从本题可以学到小写字母排在大写字母前的写法,因为小写字母ASCII码比大写字母ACSII码大,如果按字典序排的话是大写字母在小写字母前

#include <algorithm>
#include <iostream>
#include <unordered_map>

using namespace std;

const int N = 60;

int k;
unordered_map<char, int> h;

struct Node
{
    char word;
    int cnt;
    bool operator<(const Node &t) const
    {
        if (cnt != t.cnt) return cnt > t.cnt;
        if (islower(word) != islower(t.word))
            return islower(word) > islower(t.word); // 小写字母在大写字母前
        return word < t.word;
    }
} node[N];

int main()
{
    string s;
    cin >> s;
    for (auto &x : s) h[x]++;
    for (auto &x : h)
    {
        node[k++] = {x.first, x.second};
    }
    sort(node, node + k);
    for (int i = 0; i < k; i++)
    {
        printf("%c:%d;", node[i].word, node[i].cnt);
    }
    return 0;
}

3375. 成绩排序

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 1010;

int n, type;

struct Person
{
    string name;
    int score;
    int id;

    bool operator< (const Person& t) const
    {
        if(score != t.score) return score < t.score;
        return id < t.id; //如果分数相同,则序号小的在前
    }
    bool operator> (const Person& t) const 
    {
        if(score != t.score) return score > t.score; //分数不同,分数大的在前面
        return id < t.id; // 这里易写错,分数相同,序号小的在前面
    }
}q[N];

int main()
{
    cin >> n >> type;
    for (int i = 0; i < n; i ++ ) 
    {
        cin >> q[i].name >> q[i].score;
        q[i].id = i;
    }

    if(type == 0) sort(q, q + n, greater<Person>());
    else sort(q, q + n);

    for (int i = 0; i < n; i ++ ) 
        cout << q[i].name << ' ' << q[i].score << endl;

    return 0;
}

3376. 成绩排序2

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 110;

int n;
struct Person
{
    int id, score;

    bool operator< (const Person& t) const
    {
        if (score != t.score) return score < t.score;
        return id < t.id;
    }
}q[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ ) cin >> q[i].id >> q[i].score;

    sort(q, q + n);

    for (int i = 0; i < n; i ++ ) 
        cout << q[i].id << ' ' << q[i].score << endl;

    return 0;
}
posted @   Tshaxz  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
Language: HTML
点击右上角即可分享
微信分享提示