题目的主要信息:
- 输入一个字符串,字符范围在在ASCII码范围内(0~127,包括0和127),换行符表示结束,不包括换行符
- 统计字符串出现了多少种字符
方法一:位图统计法
具体做法:
既然字符数是有限的,我们可以初始化一个大小为128的全0的数组,代表0-127的ASCII码是否出现过。遍历字符串,我们每次遇到一个字符,就将数组中相应位置改成1,这样数组中0的位置就是没有出现过的字符,1的位置就是出现过的字符,最后遍历数组将所有数字相加就是字符种类。
#include<iostream>
#include<vector>
using namespace std;
int main(){
string s;
cin >> s;
vector<int> flag(128, 0);
for(int i = 0; i < s.length(); i++) //标记出现的字符
flag[s[i]] = 1;
int count = 0;
for(int i = 0; i < flag.size(); i++) //所有的0和1相加即是字符种类数
count += flag[i];
cout << count << endl;
return 0;
}
复杂度分析:
- 时间复杂度:,最坏复杂度为遍历字符串
- 空间复杂度:,辅助数组flag的大小只有128维,属于常数
方法二:集合
具体做法:
我们也可以将每种字符看成一个集合,遍历字符串将相同的字符加入到同一个集合中,最后统计集合的数量就可以了。
#include<iostream>
#include<unordered_set>
using namespace std;
int main(){
string s;
cin >> s;
unordered_set<char> set;
for(int i = 0; i < s.length(); i++)
set.insert(s[i]); //不同的字符作为一个集合
cout << set.size() << endl; //输出集合大小即可
return 0;
}
复杂度分析:
- 时间复杂度:,遍历字符串,其中无序集合的插入复杂度为
- 空间复杂度:,set的大小最多为128