问题描述
问题 - 最近,Anton 发现了一套。该集合由小英文字母组成。安东小心地将集合中的所有字母写成一行,用逗号分隔。他还在行首添加了一个开口弧形括号,并在行尾添加了一个闭合弧形括号。
不幸的是,安东有时会忘记写一些信并重新写一遍。他让你数一数他的集合中不同字母的总数。
输入 - 第一行和单行包含字母集。线的长度不超过1000。保证线从一个开口的弧形括号开始,到一个闭合的弧形括号结束。在它们之间,列出了小英文字母,用逗号分隔。每个逗号后跟一个空格。
输出 - 打印一个数字——Anton 集合中不同字母的数量。
Code Forces 问题链接 - https://codeforces.com/problemset/problem/443/A
我的代码 -
int main(){
string s;
int count=0;
getline(cin,s);
for(int i=0;i<s.length();i++){
if(s[i]==' ' || s[i]=='}' || s[i]=='{' || s[i]==','){
s.erase(i,1);
}
}
for(int i=0;i<s.length();i++){
cout << s[i];
}
sort(s.begin(),s.end());
for(int i=0;i<s.length();i++){
if(s[i]==s[i+1]){
count++;
}
}
cout << endl << (s.length()-count);
}
问题是当我输出字符串时,它还显示了我不想要的空格。输入将包含空格,例如 - {a,b,c}。 if 函数以某种方式无法从字符串中删除该空格,可能是什么问题,我该如何解决?
解决方法
正如已经发现的,问题是在擦除一个字符后,i
再次递增,跳过下一个字符。擦除后不应增加 i
。
for(int i=0;i<s.length();){
if(s[i]==' ' || s[i]=='}' || s[i]=='{' || s[i]==','){
s.erase(i,1);
} else {
i++;
}
}
但单独调用 erase()
的解决方案也是 O(N2) 因为每次 erase
都必须向前移动所有剩余字符。
考虑使用 erase-remove idiom 代替 O(N) 性能:
s.erase(std::remove_if(s.begin(),s.end(),[](char c) {
return c == ' ' || c == '}' || c == '{' || c == ',';
}),s.end());
,
擦除后下一个字符的索引将保持i
更新代码 -
int main(){
string s;
int count=0;
getline(cin,s);
for(int i=0;i<s.length();i++){
if(s[i]==' ' || s[i]=='}' || s[i]=='{' || s[i]==','){
s.erase(i,1);
i--;
}
}
for(int i=0;i<s.length();i++){
cout << s[i];
}
sort(s.begin(),s.end());
for(int i=0;i<s.length();i++){
if(s[i]==s[i+1]){
count++;
}
}
cout << endl << (s.length()-count);
}
,
执行此操作的 C++ 方法:
for(int i=0;i<s.length();i++){
if(s[i]==' ' || s[i]=='}' || s[i]=='{' || s[i]==',1);
i--;
}
应该是:
const std::string get_rid_of(",{}");
s.erase(std::remove_if(s.begin(),[=](char c)
{
return get_rid_of.find(c) != std::string::npos;
}),s.end());
,
即使您删除了一个使其跳过一个字符的字符,您也会增加 i
。正如其他人指出的那样,只有在没有 i
时才增加 erase
。
由于 C++20 可以改用 std::erase_if(std::basic_string)
函数:
std::erase_if(
s,[](char c) { return /* your condition */ ; }
);
,
您选择的迭代器类型无效,它只会擦除整个字符串。
试试这个:
string::iterator itr;
itr = s.begin();
s.erase(itr);