题目链接:Restore IP Addresses

Given a string containing only digits, restore it by returning all possible valid IP address combinations.

For example:

Given "25525511135",

return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)

这道题的要求是将一个只包含数字的字符串重新存储成IP地址的形式,返回所以情况。

注:这里的IP地址是指IPv4地址。

IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。

IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节)。IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)。

因此,需要判断一个数字字符串是否符合IP地址中的一组IP字段(即两个点分割的数字),符合的情况分为如下几种:(这里的IP字段指的是0~255)

  • 任意单个数字(0也是符合的);
  • 两个数字,则高位不为0;
  • 三个数字,则最高位为1或者2,且小于等于255,即最高位为1 或者 最高位为2且第二位小于5 或者 最高位为2且第二位等于5且最低位小于等于5。

1. 递归回溯

思路就是如果字符串s的前半部分已经生成了m个IP字段,则递归处理s的后半部分,使其生成4-m个IP字段即可。

b是字符串中字符的开始位置,n表示还需生成IP地址中的几个IP字段,ip表示已经生成的IP地址。

递归终止条件是n为0,此时如果扫描到字符串的最后,即b等于字符串长度,说明生成的IP地址符合要求,存储起来即可。

时间复杂度:O(???)

空间复杂度:O(???)

 1 class Solution
 2 {
 3     vector<string> vs;
 4 public:
 5     vector<string> restoreIpAddresses(string s)
 6     {
 7         restoreIpAddresses(s, 0, 4, "");
 8         return vs;
 9     }
10 private:
11     void restoreIpAddresses(string &s, int b, int n, string ip)
12     {
13         if(n == 0)
14         {
15             if(b == s.size())
16                 vs.push_back(ip);
17             return;
18         }
19         
20         for(int i = b + 1; i <= s.size(); ++ i)
21         {
22             string temp = s.substr(b, i - b);
23             if(isIP(temp))
24                 restoreIpAddresses(s, i, n - 1, ip == "" ? temp : ip + "." + temp);
25             else
26                 break;
27         }
28     }
29     bool isIP(string s)
30     {
31         if(s.size() == 1 || (s.size() == 2 && s[0] != '0') || (s.size() == 3 &&
32             (s[0] == '1' || s[0] == '2' && (s[1] < '5' || s[1] == '5' && s[2] <= '5'))))
33             return true;
34         return false;
35     }
36 };

2. 字符串分割

由于IP地址分为4段,因此,可以考虑把字符串S分割成4段,并且每段最多3个数字字符。如果这四段都符合IP字段的要求,则表明此种分割方式可以生成IP地址,存储起来即可。

时间复杂度:O(???)

空间复杂度:O(???)

 1 class Solution
 2 {
 3 public:
 4     vector<string> restoreIpAddresses(string s)
 5     {
 6         vector<string> vs;
 7         for(int i = 1; i < 4 && i < s.size(); ++ i)
 8             for(int j = i + 1; j < i + 4 && j < s.size(); ++ j)
 9                 for(int k = j + 1; k < j + 4 && k < s.size(); ++ k)
10                 {
11                     string s1 = s.substr(0, i), s2 = s.substr(i, j - i), 
12                            s3 = s.substr(j, k - j), s4 = s.substr(k, s.size() - k);
13                     if(isIP(s1) && isIP(s2) && isIP(s3) && isIP(s4))
14                         vs.push_back(s1 + "." + s2 + "." + s3 + "." + s4);
15                 }
16         return vs;
17     }
18 private:
19     bool isIP(string s)
20     {
21         if(s.size() == 1 || (s.size() == 2 && s[0] != '0') || (s.size() == 3 &&
22             (s[0] == '1' || s[0] == '2' && (s[1] < '5' || s[1] == '5' && s[2] <= '5'))))
23             return true;
24         return false;
25     }
26 };