题目的主要信息:
- 输入的字符串由26个字母组成,大小写都有
- 定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和
- 每个字母都有一个“漂亮度”,范围在1到26之间,没有任何两个不同字母拥有相同的“漂亮度”
- 漂亮度统计时字母忽略大小写
方法一:排序
具体做法:
题目的意思就是26个字母每个字母有一个1-26的漂亮度,不重复,要是该字符串漂亮度最大,则直接使它里面出现次数最多的字符漂亮度最大即26,出现次多的字符漂亮度为25,以此递减,然后相加就会得到最大的漂亮度。
我们可以用一个长度为26的数组统计每个字符串出现的次数,然后对数组进行排序,从数组末尾开始遍历数组,末尾的即最多的次数乘上最高漂亮度26,往前遍历漂亮度依次递减相加即可。
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int n;
while(cin >> n){
while(n--){
string s;
cin >> s;
vector<int> count(26, 0); //用于统计26个字母每个字符串中出现的次数
for(int i = 0; i < s.length(); i++){ //遍历字符串统计字母出现次数
if(s[i] >= 'a' && s[i] <= 'z') //小写字母
count[s[i] - 'a']++;
else //大写字母
count[s[i] - 'A']++;
}
sort(count.begin(), count.end()); //出现次数排序
int output = 0;
int k = 26;
for(int i = 25; i >= 0; i--){ //出现次数最多的漂亮度最大26,依次递减
output += count[i] * k;
k--;
}
cout << output << endl;
}
}
return 0;
}
复杂度分析:
- 时间复杂度:,其中为字符串的长度,排序的数组和累加计算漂亮度都是26,常数时间
- 空间复杂度:,辅助数组的长度为26,常数空间
方法二:哈希表+优先队列
具体做法:
我们也可以用一个无序哈希表统计每个字符串出现的次数,然后遍历哈希表将value值加入一个优先队列中进行排序,最后依次弹出优先队列中的元素,也是从漂亮度最大26开始乘,后面漂亮度递减,不断累加。
这个方法如果字符集不足26个字母的时候时间空间都会更低一些。
#include<iostream>
#include<string>
#include<queue>
#include<unordered_map>
#include<algorithm>
using namespace std;
int main(){
int n;
while(cin >> n){
while(n--){
string s;
cin >> s;
unordered_map<char, int> mp;
for(int i = 0; i < s.length(); i++){
char c = tolower(s[i]); //将字母全部转为小写
mp[c]++; //哈希表统计每个字母出现次数
}
priority_queue<int> pq;
for(auto iter = mp.begin(); iter != mp.end(); iter++) //遍历哈希表
pq.push(iter->second); //将value值加入优先队列
int output = 0;
int k = 26;
while(!pq.empty()){ //遍历优先队列
output += pq.top() * k; //次数最多的用26开始设置漂亮度
pq.pop();
k--;
}
cout << output << endl;
}
}
return 0;
}
复杂度分析:
- 时间复杂度:,其中为字符串的长度,遍历字符串统计为,遍历哈希表加入复杂度为字符集,常数时间,后面优先队列排队和弹出也是常数时间
- 空间复杂度:,辅助数组的长度为26,常数空间