题目来源
题目描述
题目解析
优先队列
- 先用unordered_map统计每个字母出现的频率,key为char,value为cnt
- 然后利用priority_queue有限队列的特性
- 有限队列默认是个大根堆,大的数在前面
- pair排序规则:先根据first(cnt)排序;如果first相等,那么根据second(char)排序
- 然后不断从priority_queue取出数据,压入结果字符串中
class Solution {
public:
string frequencySort(string s) {
std::unordered_map<char, int> m;
for(auto ch : s){
++m[ch];
}
std::priority_queue<std::pair<int, char>> q;
for(auto it : m){
q.push({it.second, it.first});
}
std::string ans;
while (!q.empty()){
auto t = q.top(); q.pop();
ans.append(t.first, t.second);
}
return ans;
}
};
重写sort的cmp
我们也可以使用STL自带的sort来做,关键就在于重写comparator,由于需要使用外部变量,记得中括号中放入&,然后我们将频率大的返回,注意一定还要处理频率相等的情况,要不然两个频率相等的字符可能穿插着出现在结果res中,这样是不对的。参见代码如下:
class Solution {
public:
string frequencySort(string s) {
std::unordered_map<char, int> m;
for(auto ch : s){
++m[ch];
}
std::sort(s.begin(), s.end(), [&](char &a, char &b){
return m[a] > m[b] || (m[a] == m[b] && a < b); // 如果频率相同,那么小的放到前面
});
return s;
}
};
计数排序
我们也可以不用优先队列,而是建立一个字符串数组,因为某个字符的出现次数不可能超过s的长度,所以我们将每个字符根据其出现次数放入数组中的对应位置,那么最后我们只要从后往前遍历数组所有位置,将不为空的位置的字符串加入结果res中即可,参见代码如下:
class Solution {
public:
string frequencySort(string s) {
std::unordered_map<char, int> m;
for(auto ch : s){
++m[ch];
}
std::string ans;
std::vector<std::string> vec(s.size() + 1);
for(auto & a : m){
vec[a.second].append(a.second, a.first);
}
for (int i = s.size(); i > -1; --i) {
if(!vec[i].empty()){
ans.append(vec[i]);
}
}
return ans;
}
};