题目的主要信息:

  • 输入一个字符串,字符范围在在ASCII码范围内(0~127,包括0和127),换行符表示结束,不包括换行符
  • 统计字符串出现了多少种字符

方法一:位图统计法

具体做法:

既然字符数是有限的,我们可以初始化一个大小为128的全0的数组,代表0-127的ASCII码是否出现过。遍历字符串,我们每次遇到一个字符,就将数组中相应位置改成1,这样数组中0的位置就是没有出现过的字符,1的位置就是出现过的字符,最后遍历数组将所有数字相加就是字符种类。

alt

#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;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),最坏复杂度为遍历字符串
  • 空间复杂度:O(1)O(1),辅助数组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;
}

复杂度分析:

  • 时间复杂度:O(n)O(n),遍历字符串,其中无序集合的插入复杂度为O(1)O(1)
  • 空间复杂度:O(1)O(1),set的大小最多为128