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

题目来源

题目描述

在这里插入图片描述

题目解析

优先队列

  • 先用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;
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值