题目的主要信息:
- 一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果
- 一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果
- 输入的字符串长度
方法一:哈希表统计+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;
}
复杂度分析:
- 时间复杂度:,遍历字符串用哈希表统计每种字符出现的次数,一共次,每次,vector数组大小最多为字符集,即10+26,所以排序也是常数时间
- 空间复杂度:,vector数组和map都是字符集大小,即10+26,常数空间
方法二:桶排序思想
具体做法:
用桶排序的思想,准备123个桶(因为最大的z的ASCⅡ码为122),每个桶相应ASCⅡ码字符出现的次数,然后找到最大出现次数。然后最大出现次数依次递减,从小到大遍历桶,输出与每次次数相等的字符即可。
#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;
}
复杂度分析:
- 时间复杂度:,遍历字符串统计出现次数,以及遍历所有的次数输出
- 空间复杂度:,辅助数组hash的大小为常数