451. 根据字符出现频率排序
题目
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。
返回 已排序的字符串 。如果有多个答案,返回其中任何一个。
提示:
1 <= s.length <= 5 * 105s由大小写英文字母和数字组成
示例
示例 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 自定义排序
- 使用无序map存储字符和出现次数映射关系
- 在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 提供了两个公开的成员变量 first 和 second,分别用于访问这对元素中的第一个和第二个值。
vector<pair<int,int>> vec;
这里定义了一个 vector,它的元素类型是 pair<int, int>。这意味着 vec 可以存储一系列整数对,每个整数对由两个 int 类型的值组成。你可以使用 vec.push_back(make_pair(a, b)) 来添加新的整数对到这个向量中,其中 a 和 b 是你想要存储的两个整数。你也可以通过下标操作符 [] 或者迭代器来访问和修改向量中的元素。
访问pair<int,int>的元素使用first和second,注意不要括号!!!
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 函数调用包含三个部分:
-
vec.begin(), vec.end():这是要排序的范围,begin()返回指向vec第一个元素的迭代器,end()返回指向vec末尾(最后一个元素之后的位置)的迭代器。 -
一个 lambda 表达式作为比较函数:
[] (const pair<int,int> &p1, const pair<int,int> &p2) { return p1.second > p2.second; }。这个 lambda 表达式接收两个pair<int, int>类型的参数p1和p2,并返回一个布尔值。如果p1.second大于p2.second,则返回true,表示p1应该排在p2后面;否则返回false,表示p1应该排在p2前面。这里的比较是基于pair的second成员进行的。 -
排序的行为:由于 lambda 表达式中使用了
>操作符,所以sort函数会将vec中的元素按照pair的second成员从大到小的顺序进行排序。
简而言之,这段代码的作用是将 vec 中的元素按照每个元素的 pair 的 second 成员值从大到小排序。如果 second 成员值相同,则 first 成员的值不会影响排序结果,因为 std::sort 只考虑提供的比较函数。
C++相关语法:头文件 <queue> 中的优先队列 priority_queue
在 C++ 中,优先队列是一种特殊的队列,它不遵循先进先出(FIFO)的原则,而是根据元素的优先级来出队。在 C++ 标准库中,优先队列是通过std::priority_queue 容器适配器实现的。std::priority_queue 默认是一个最大堆,即队首元素是最大的。如果你需要一个最小堆,可以通过传递一个自定义的比较函数来实现。
-
自动排序:优先队列在插入新元素时会自动根据元素的优先级进行排序。
-
只访问队首元素:你只能访问优先队列的队首元素,即优先级最高的元素。
-
不提供索引访问:与
std::vector或std::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;
}

被折叠的 条评论
为什么被折叠?



