题目的主要信息:

输入一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASCII码由小到大排序输出。

方法一:

用map建立字符和次数之间的映射,首先遍历一遍字符串统计每个字符出现的次数。总共有n个字符,字符最大出现次数最大为n,从n开始往下遍历,在map中按照ASCII码的大小查找是否有该次数的字符,如果有的话把它加到res中。最后输出res。

具体做法:

#include<iostream>
#include<map>
#include<string>
#include<algorithm>

using namespace std;

int main()
{
    string str;
    map<char,int> mp;
    while(getline(cin,str))
    {    
        map<char,int> mp;
        for(int i=str.size()-1;i>=0;i--){//统计出现次数
            mp[str[i]]++;
        }
        string res;
        for(int i=str.size();i>=0;i--)//按照大小排序
        {
            for(auto x:mp)//按照ASCII码的大小遍历一遍mp
            {
                if(x.second==i){//如果有字符次数为i的则把该字符添加到res中
                    res += x.first;
                }
            }
        }
        cout<<res<<endl;
    }
    
    return 0;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),需要遍历一遍字符串。
  • 空间复杂度:O(n)O(n),最坏情况下,每种字符只出现一次,mp需要n个空间。

方法二:

用map建立字符和次数之间的映射,首先遍历一遍字符串统计每个字符出现的次数。然后重载sort函数,对所有映射进行排序,出现次数较大的在前面,若出现次数相同,则ASCII码较大的字符在前面,最后输出排序后的映射的字符。 alt

具体做法:

#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<char,int> a,pair<char,int> b){
    if(a.second==b.second){//当出现次数相同时
        return a.first<b.first;//输出ASCII码较小的字符
    }
    return a.second>b.second;//输出出现次数较多的字符
}
int main(){
    string s;
    while(cin>>s){
        map<char,int> mp;
        for(int i=0;i<s.size();i++){//逐个统计字符出现次数
            mp[s[i]]++;
        }
        vector<pair<char,int> > v(mp.begin(),mp.end());
        sort(v.begin(),v.end(),cmp);//按照出现次数进行排序
        for(auto it:v){
            cout<<it.first;//按照次数大小输出
        }
        cout<<endl;
    }
}

复杂度分析:

  • 时间复杂度:O(nlog2n)O(nlog_2n),sort函数的时间复杂度为O(nlog2n)O(nlog_2n)
  • 空间复杂度:O(n)O(n),最坏情况下,每种字符只出现一次,mp需要n个空间。