I am doing the IP defanging challenge on Leetcode using C++. The following is my attempt at the solution:
class Solution {
public:
string defangIPaddr(string address) {
for(int i = 0; i < address.size(); i++){
if(address[i] == '.'){
address.replace(i, 1, "[.]");
}
}
return address;
}
};
Here, the code is not able to replace the period with "[.]"
, it returns "Time Limit Exceeded" instead.
I tried replacing it with "[]"
and it works fine, and so does it for every other possible string combination. I tried escaping, but even that doesn't work.
Is "[.]"
some special string that cannot be read? I do know there is a solution where you concatenate strings iteratively, but shouldn't this work too?
When the loop encounters the first .
, it replaces the .
with [.]
, thus increasing the string's size
. But the loop is not adjusting i
to account for the newly inserted [
, so the next iteration will see the same .
after that new [
and perform the same replacement again, and again, and again, endlessly. That is why your solution is timing out.
You need to make sure you are advancing i
past the replacement text, eg:
class Solution {
public:
string defangIPaddr(string address) {
for(string::size_type i = 0; i < address.size(); ++i){
if (address[i] == '.'){
address.replace(i, 1, "[.]");
i += 2; // <-- skip to ']', the subsequent ++i will then skip past it
}
}
return address;
}
};
Alternatively, use a while
loop instead of a for
loop, then you can decide more easily how much to increment i
each time:
class Solution {
public:
string defangIPaddr(string address) {
string::size_type i = 0;
while (i < address.size()){
if (address[i] == '.'){
address.replace(i, 1, "[.]");
i += 3;
}
else {
++i;
}
}
return address;
}
};
Personally, I would use std::string::find()
in the loop instead, eg:
class Solution {
public:
string defangIPaddr(string address) {
string::size_type i = 0;
while ((i = address.find('.', i)) != string::npos){
address.replace(i, 1, "[.]");
i += 3;
}
return address;
}
};
Let's look at a sample input, bo.y
. When i
is 2, replace
turns the string to bo[.]y
. Then, when i
is 3, it sees that pesky .
again, and replace
turns it to bo[[.]]y
. This keeps happening until it times out.
The fix? increment i after you call replace:
class Solution {
public:
string defangIPaddr(string address) {
for(int i = 0; i < address.size(); i++){
if(address[i] == '.'){
address.replace(i, 1, "[.]");
i++;
}
}
return address;
}
};
As explained in Remy's answer , your problem lies in the fact that the loop counter never gets past the 'new' '.'
character when you increase the string's length.
Although that answer is, in itself, faultless, I find that it is often far simpler, in any string replacement and/or substitution operation, to avoid trying to do the work 'inline'; rather, it is most often much easier to make a copy, replacing the copied parts as and when necessary:
class Solution {
public:
string defangIPaddr(string address)
{
string answer{ "" }; // Local string to build the answer - start off empty.
answer.reserve(address.size() * 2); // Reserve sufficient space to avoid multiple reallocation.
for (size_t i = 0; i < address.size(); i++) {
if (address[i] == '.') {
answer += "[.]"; // For a dot, replace with the "[.]" string ...
}
else {
answer += address[i]; // ... otherwsie, just copy the character.
}
}
answer.shrink_to_fit(); // Free any unneeded memory.
return answer; // We return BY VALUE, so a copy is made of the LOCAL "answer".
}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.