简体   繁体   中英

Leetcode - Defanging IP address

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

Live Demo

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

Live Demo

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

Live Demo

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM