451. 根据字符出现频率排序-LeetCode(C++)

451. 根据字符出现频率排序

题目

给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。

返回 已排序的字符串 。如果有多个答案,返回其中任何一个。

提示:

  • 1 <= s.length <= 5 * 105
  • s 由大小写英文字母和数字组成
示例

示例 1:

输入: s = "tree"
输出: "eert"
解释: 'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。

示例 2:

输入: s = "cccaaa"
输出: "cccaaa"
解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

输入: s = "Aabb"
输出: "bbAa"
解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。
题解1 - 利用 vector 自定义排序

来自利用vector自定义排序

  1. 使用无序map存储字符和出现次数映射关系
  2. 在vector中存储pair对,利用vector自定义排序
class Solution {
public:
    string frequencySort(string s) {
        unordered_map<int,int> hashmap;
        for(char ch : s){
            ++hashmap[ch];
        }
        string result;
        vector<pair<int,int>> vec;
        for (const auto &m : hashmap) {
            vec.push_back(m);
        }
        sort(vec.begin(),vec.end(),[] (const pair<int,int> &p1, const pair<int,int> &p2){
            return p1.second > p2.second;
        });
        for(const auto & v : vec){
            for(int i = 0;i < v.second;i++){
                result += v.first;
            }
        }
        return result;
    }
};
题解2 - 利用优先队列

来自利用优先队列

当使用 pair<int, char> 作为 priority_queue 的元素类型时,C++ 会使用 std::less<pair<int, char>> 作为默认的比较函数。std::less<pair<int, char>> 的行为是首先比较 pair 的第一个元素(在这个例子中是 int 类型的频率)。如果第一个元素相等,它会继续比较第二个元素(在这个例子中是 char 类型的字符)。

class Solution {
public:
    string frequencySort(string s) {
        unordered_map<char, int> ump;
        for (const auto &c : s) {
            ++ump[c];
        }
        priority_queue<pair<int, char>> pq;
        for (const auto &m : ump) {
            pq.push({m.second, m.first});
        }        
        string ret;
        while (!pq.empty()) {
            auto t = pq.top(); 
            pq.pop();
            ret.append(t.first, t.second);
        }
        return ret;
    }
};
C++相关语法: pair 模板类

在 C++ 标准库中,pair 是一个模板类,用于存储一对元素,这两个元素可以是不同的数据类型。pair 通常用于函数返回两个值的场景,或者在容器中存储两个相关联的数据项。

例如,如果你有一个 pair<int, int> 类型的对象,它可以存储两个 int 类型的值。pair 提供了两个公开的成员变量 firstsecond,分别用于访问这对元素中的第一个和第二个值。

vector<pair<int,int>> vec;

这里定义了一个 vector,它的元素类型是 pair<int, int>。这意味着 vec 可以存储一系列整数对,每个整数对由两个 int 类型的值组成。你可以使用 vec.push_back(make_pair(a, b)) 来添加新的整数对到这个向量中,其中 ab 是你想要存储的两个整数。你也可以通过下标操作符 [] 或者迭代器来访问和修改向量中的元素。

访问pair<int,int>的元素使用firstsecond,注意不要括号!!!

for(const auto & v : vec){
    for(int i = 0;i < v.second;i++){
        result += v.first;
    }
}
C++相关语法:利用 vector 自定义排序
sort(vec.begin(),vec.end(),[] (const pair<int,int> &p1, const pair<int,int> &p2){
    return p1.second > p2.second;
});

这段代码是 C++ 中使用 std::sort 函数对 vector<pair<int, int>> 类型的容器 vec 进行排序的示例。std::sort 是 C++ 标准库中的一个非常强大的算法,它可以根据指定的比较函数对序列进行排序。

这里的 sort 函数调用包含三个部分:

  1. vec.begin(), vec.end():这是要排序的范围,begin() 返回指向 vec 第一个元素的迭代器,end() 返回指向 vec 末尾(最后一个元素之后的位置)的迭代器。

  2. 一个 lambda 表达式作为比较函数:[] (const pair<int,int> &p1, const pair<int,int> &p2) { return p1.second > p2.second; }。这个 lambda 表达式接收两个 pair<int, int> 类型的参数 p1p2,并返回一个布尔值。如果 p1.second 大于 p2.second,则返回 true,表示 p1 应该排在 p2 后面;否则返回 false,表示 p1 应该排在 p2 前面。这里的比较是基于 pairsecond 成员进行的。

  3. 排序的行为:由于 lambda 表达式中使用了 > 操作符,所以 sort 函数会将 vec 中的元素按照 pairsecond 成员从大到小的顺序进行排序。

简而言之,这段代码的作用是将 vec 中的元素按照每个元素的 pairsecond 成员值从大到小排序。如果 second 成员值相同,则 first 成员的值不会影响排序结果,因为 std::sort 只考虑提供的比较函数。

C++相关语法:头文件 <queue> 中的优先队列 priority_queue

在 C++ 中,优先队列是一种特殊的队列,它不遵循先进先出(FIFO)的原则,而是根据元素的优先级来出队。在 C++ 标准库中,优先队列是通过std::priority_queue 容器适配器实现的。std::priority_queue 默认是一个最大堆,即队首元素是最大的。如果你需要一个最小堆,可以通过传递一个自定义的比较函数来实现。

  • 自动排序:优先队列在插入新元素时会自动根据元素的优先级进行排序。

  • 只访问队首元素:你只能访问优先队列的队首元素,即优先级最高的元素。

  • 不提供索引访问:与 std::vectorstd::list 不同,你不能通过索引直接访问优先队列中的元素。

  • 构造:可以指定一个比较函数来定义优先级。

  • push:向队列中添加元素。

  • pop:移除队首元素。

  • top:访问队首元素,但不移除它。

  • empty:检查队列是否为空。

  • size:返回队列中的元素数量。

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int main() {
    // 创建一个最小堆优先队列
    priority_queue<int, vector<int>, greater<int>> minHeap;
    priority_queue<int> maxHeap;
    
    // 添加元素
    minHeap.push(30);
    minHeap.push(10);
    minHeap.push(20);

    // 打印队首元素
    cout << "The smallest element is " << minHeap.top() << endl;

    // 移除队首元素
    minHeap.pop();

    // 再次打印队首元素
    cout << "The next smallest element is " << minHeap.top() << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值