题目的主要信息:

  • 一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果
  • 一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果
  • 输入的字符串长度[1,1000][1,1000]

方法一:哈希表统计+sort排序

具体做法:

我们可以用unordered_map统计字符串中每个字符出现的次数,然后将unordered_map记录的内容送入pair型的vector中,对其进行sort排序。sort排序我们需要重载大小比较,当次数不相等时,返回次数大的为true,当次数相等时返回ASCⅡ码小的为true。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;

bool cmp(const pair<char, int>& a, const pair<char, int>& b){ //重载大小比较
   if(a.second != b.second) //优先是个数降序
       return a.second > b.second;
   else //再是ASCⅡ升序
       return a.first < b.first;
}

int main(){
    string s;
    while(cin >> s){
        unordered_map<char, int> mp;
        for(int i = 0; i < s.length(); i++) //哈希表统计每个字符出现的次数
            mp[s[i]]++;
        vector<pair<char, int> > record(mp.begin(), mp.end());
        sort(record.begin(), record.end(), cmp); //排序
        for(int i = 0; i < record.size(); i++) //输出
            cout << record[i].first; 
        cout << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),遍历字符串用哈希表统计每种字符出现的次数,一共nn次,每次O(1)O(1),vector数组大小最多为字符集,即10+26,所以排序也是常数时间
  • 空间复杂度:O(1)O(1),vector数组和map都是字符集大小,即10+26,常数空间

方法二:桶排序思想

具体做法:

用桶排序的思想,准备123个桶(因为最大的z的ASCⅡ码为122),每个桶相应ASCⅡ码字符出现的次数,然后找到最大出现次数。然后最大出现次数依次递减,从小到大遍历桶,输出与每次次数相等的字符即可。

alt

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

int main(){
    string s;
    while(cin >> s){
        vector<int> hash(123, 0); //统计字母和数字出现的次数
        int count = 0; //记录最高次数
        for(int i = 0; i < s.length(); i++){ 
            hash[s[i]]++;
            count = max(count, hash[s[i]]);
        }
        while(count){ //遍历所有的次数
            for(int i = 0; i < 123; i++) //从ASCⅡ码低到高找符合的输出
                if(hash[i] == count)
                    cout << (char)i;
            count--;
        }
        cout << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),遍历字符串统计出现次数,以及遍历所有的次数输出
  • 空间复杂度:O(1)O(1),辅助数组hash的大小为常数