Day03 2023/01/10
难度:简单
题目
编写一个函数,计算字符串中含有的不同字符的个数。字符在 ASCII 码范围内( 0~127 ,包括 0 和 127 ),换行表示结束符,不算在字符里。不在范围内的不作统计。多个相同的字符只计算一次 。例如,对于字符串 abaca 而言,有 a、b、c 三种不同的字符,因此输出 3 。 数据范围:1 ≤ n ≤ 500。
输入描述:
输入一行没有空格的字符串。
输出描述:
输出 输入字符串 中范围在(0~127,包括0和127)字符的种数。
示例1
输入:abc
输出:3
说明:字符串中含有三个不同的字符
示例2
输入:bbb
输出:1
说明:字符串中只含有1个不同的字符
思路一
使用数组记录每种字符是否已经出现
根据题目要求字符在 ASCII 码范围内( 0~127 ,包括 0 和 127 )。呢我们只需要维护一个大小为128的数组用来比较字符,让输入的字符作为数组下标,取出这个下标数组中的字符直接与输入的字符比较,如果相同则跳过,不同则赋值,让计数器+1,最后返回计数器即可。
思路二
使用集合来统计每种字符是否已经出现
利用c++中set容器(即集合)的有序性 (每次向集合中添加元素时,如果集合中已经有该元素,不会重复添加;如果集合中没有该元素,则会添加新元素。遍历字符串将每个字符添加到集合中)最后统计集合的大小,就是字符的种类数目。(注:在C/C++中set的实现是红黑树)
关键点
- 思路一的实现方式中,由于一开始维护数组中所有的元素的初值都为-1(只要不在 0-127 这个范围内),所以最初满足
if判断的时候都是初次遇到 未被记录 到数组中的 字符。一旦被数组记录后,在遇到该字符就会直接跳过了。
算法实现
c++代码实现1-使用数组记录每种字符是否已经出现
#include <iostream>
#include <vector>
#include <string>
#include <set>
using namespace std;
//方法一:使用数组记录每种元素是否已经出现
int main(){
vector<char> asc(128,-1); //定义统计数组,长度为固定128,初始每个元素均为-1
int count=0; //计数器
string s; //输入字符串
cout << "请输入字符串:" << endl;
getline(cin , s); //获取整行字符串
//遍历字符串
for(auto it = s.begin(); it != s.end(); it++){
if(asc[int(*it)] != *it){ //和数组元素进行比较,不相等(当前元素还未出现)
asc[int(*it)] = *it; //当前数组元素等于字符元素
count++; //计数器加1
}
}
cout << "不相同的字符一共有:" << count << endl;
return 0;
}
- 时间复杂度 --- 这里 n 为字符串长度
- 空间复杂度 --- 仅额外声明了一个长度为128的数组
c++代码实现2-使用集合来统计每种字符是否已经出现
#include <iostream>
#include <vector>
#include <string>
#include <set>
using namespace std;
//方法二:使用集合来统计
int main() {
set<char> asc; //定义统计集合(容器)
int count=0; //计数器
string s; //输入字符串
cout << "请输入字符串:" << endl;
getline(cin , s); //获取整行字符串
for(int i = 0; i< s.length(); i++){ //向集合中添加元素
asc.insert(s.at(i));
}
cout << "不相同的字符一共有:" << asc.size() <<endl;
return 0;
}
- 时间复杂度 --- 向集合中插入元素时间复杂度为 ,然后插入 n 个元素(其中 n 为字符串中所含不同字符的个数)
- 空间复杂度为 --- 其中 n 为字符串中所含不同字符的个数
总结
- 在算法的解题过程中在我们了解编程语言所提供的一些库函数和数据类型特点时,在考虑到该库函数或者种数据类型在实现问题时所需的 时间和空间复杂度 是否没有远大于利用传统算法实现所花费的 时间和空间复杂度 高的情况下再考虑使用它解题。(不要盲目的使用编程语言提供的方法去解题)