题目描述
现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
例如:
给出的字符串为"25525522135",
返回["255.255.22.135", "255.255.221.35"].

方法一:暴力求解
求解思路
直接对所给的字符串进行枚举,因为IP地址每一个位置可能有1到3个数字,因此我们对每一个位置进行1到3字符串大小的遍历。这样既可求出所有的IP地址
图片说明
解题代码

class Solution {
public:
     bool justify(string s)//参考漫漫云天自翱翔的code
     {
        if(s.size() != 1 && s[0] == '0' || stoi(s) > 255) return true;
        //这个地方判断IP地址的时候,是为了防止出现大于255的数字组合出现,
        //并且防止类似025这种类型的数字组合出现!
        return false;
     }
    vector<string> restoreIpAddresses(string s) {
        // write code here
        vector<string> ans;
        for(int i = 1;i<=3;i++)
        {   //第一位的长度
            for(int j = 1;j<=3;j++)
            {  //第二位的长度
                for(int m = 1;m<=3;m++)
                {  //第三位的长度
                    for(int n = 1;n<=3;n++)
                    {  // 第四位的长度
                         if((i+j+m+n)==s.size())
                         {
                            string s1 = s.substr(0,i);//取子串
                            string s2 = s.substr(i,j);
                            string s3 = s.substr(i+j,m);
                            string s4 = s.substr(i+j+m,n);
                            if(!justify(s1)&&!justify(s2)&&!justify(s3)&&!justify(s4))
                            {
                                string tt = s1 + "." +s2 +"." +s3 +"." +s4;  //拼接
                                ans.push_back(tt);//将所有结果进行保存,最后输出结果。
                            }
                        }    
                    }
                }
            }
        }
        return ans;
    }
};

复杂度分析
时间复杂度:因为四个遍历都是从1到3的循环,为常数,因此为O(1)
空间复杂度:使用子串,空间复杂度为O(1)

方法二:递归的思想
求解思路
使用递归的思想,把数字字符串进行分割,然后在分割的基础上面继续分割,如果遇到不符合IP地址的格式,则这一“分支”的递归就结束,然后再看其他分割的结果。
其中参考杭电 De梦的终止条件和段位合法性,我们有:当IP地址的点的数量达到3个时,停止递归。对于段位的合法性,可以参考方法一的暴力法求解,即不能出现格式不符合IP地址的数字组合。
图片说明
解题代码

class Solution {
private:
    vector<string> result;// 记录结果 参考杭电 De梦的code
    void backtracking(string& s, int startIndex, int pointNum)//startIndex:搜索的起始位置,pointNum:添加逗点的数量
    {
        if (pointNum == 3) 
        { // 逗点数量为3时,分隔结束
            // 判断第四段子字符串是否合法,如果合法就放进result中
            if (isValid(s, startIndex, s.size() - 1)) 
            {
                result.push_back(s);
            }
        }
        for (int i = startIndex; i < s.size(); i++) 
        {
            if (isValid(s, startIndex, i)) 
            { // 判断 [startIndex,i] 这个区间的子串是否合法
                s.insert(s.begin() + i + 1 , '.');  // 在i的后面插入一个逗点
                pointNum++;
                backtracking(s, i + 2, pointNum);   // 插入逗点之后下一个子串的起始位置为i+2
                pointNum--;                         // 回溯
                s.erase(s.begin() + i + 1);         // 回溯删掉逗点
            } else break; // 不合法,直接结束本层循环
        }
    }
    bool isValid(const string& s, int start, int end) 
    {
        if (start > end) 
        {
            return false;// 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法
        }
        if (s[start] == '0' && start != end) 
        { 
                return false;//0开头不合法
        }
        int num = 0;
        for (int i = start; i <= end; i++) 
        {
            if (s[i] > '9' || s[i] < '0') //非正整数字符不合法
            { 
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if (num > 255) // 段位值大于255不合法
            {
                return false;
            }
        }
        return true;
    }
public:
    vector<string> restoreIpAddresses(string s) {
        result.clear();
        if (s.size() > 12) return result;
        backtracking(s, 0, 0);
        return result;
    }
};

复杂度分析
时间复杂度:递归所消耗的时间,为O(图片说明 )(参考De 梦)
空间复杂度:递归使用的空间,O(N)