I'm doing kata on codewars, and I need something like this:
When a letter in string occures two times - delete both.
I've done something like this:
std::string str2 = str;
for(int i=0;i<str2.size();i++){
for(int j=0;j<str2.size();j++){
if(std::tolower(str2[i]) == std::tolower(str2[j]) && j != i){
n++;
str2.erase(str2.begin() + i);
str2.erase(str2.begin() + j);
i--;
j--;
}
}
}
And getting core dumped ( it's caused by str2.erase(str2.begin() + i);
). I know it is somewhere my mistake with memory, but can You tell me what is wrong with this? I analyzed and didn't see anything bad there.
First, we can observe that when an erasure occurs we'll always have i<j
.
Now if you delete the first char and then the second, you're shooting at a moving target: you need to adjust to the new position of the second char after having erased the first one:
str2.erase(str2.begin() + i);
str2.erase(str2.begin() + j-1); // because former j c[j] is now c[j-1]
Another variant that is also suitable is to delete the second char first (doesn't change the position of the first):
str2.erase(str2.begin() + j); // because j> i it has no impact on i
str2.erase(str2.begin() + i);
Unrelated, but we could also make use of our deduction on i<j
to optimise or loop and save a significant number of useless comparisons:
for(int i=0;i<str2.size();i++) {
for(int j=i+1;j<str2.size();j++) {
...
}
}
Another problem is that you perform i--
in the inner loop, when i
doesn't get incremented. This will have two consequences you will redo comparisons that you already do. So just remove this decrement, and restart with j=i+1
.
Your algorithm does remove pairs of letters only. So if you have more than 2 occurrences of a letter, only the two first will get removed. So you need to review your algorithm (attention to not erase several time the first occurence either ;-) )