题目链接
tag:
- Medium;
question:
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
Example:
Input: "25525511135"
Output: ["255.255.11.135", "255.255.111.35"]
思路:
本题要求复原IP地址。IP地址由32位二进制数组成,为便于使用,常以 XXX.XXX.XXX.XXX
形式表现,每组XXX代表小于或等于255的10进制数。所以说IP地址总共有四段,每一段可能有一位,两位或者三位,范围是[0, 255],题目明确指出输入字符串只含有数字,所以当某段是三位时,我们要判断其是否越界(>255),还有一点很重要的是,当只有一位时,0可以成某一段,如果有两位或三位时,像 00, 01, 001, 011, 000等都是不合法的,所以我们还是需要有一个判定函数来判断某个字符串是否合法。这道题其实也可以看做是字符串的分隔问题,在输入字符串中加入三个点,将字符串分为四段,每一段必须合法,求所有可能的情况。
解法一:暴力搜索
由于每段数字最多只能有三位,而且只能分为四段,所以情况并不是很多,我们可以使用暴力搜索的方法,每一段都循环1到3,然后当4段位数之和等于原字符串长度时,我们进一步判断每段数字是否不大于255,然后滤去不合要求的数字,加入结果中即可,代码如下:
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
for (int a=1; a<4; ++a) {
for (int b=1; b<4; ++b) {
for (int c=1; c<4; ++c) {
for (int d=1; d<4; ++d) {
if (a + b + c + d == s.size()) {
int A = stoi(s.substr(0, a));
int B = stoi(s.substr(a, b));
int C = stoi(s.substr(a + b, c));
int D = stoi(s.substr(a + b + c, d));
if (A <= 255 && B <= 255 && C <= 255 && D <= 255) {
string t = to_string(A) + "." + to_string(B) + "." + to_string(C) + "." + to_string(D);
if (t.size() == s.size() + 3)
res.push_back(t);
}
}
}
}
}
}
return res;
}
};
解法二:递归
我们用k来表示当前还需要分的段数,如果k = 0,则表示三个点已经加入完成,四段已经形成,若这时字符串刚好为空,则将当前分好的结果保存。若k != 0, 则对于每一段,我们分别用一位,两位,三位来尝试,分别判断其合不合法,如果合法,则调用递归继续分剩下的字符串,最终和求出所有合法组合,代码如下:
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
helper(s, 4, "", res);
return res;
}
void helper(string s, int k, string out, vector<string> &res) {
if (k == 0) {
if (s.empty())
res.push_back(out);
}
else {
for (int i=1; i<=3; ++i) {
if (s.size() >= i && isValid(s.substr(0, i))) {
if (k == 1)
helper(s.substr(i), k - 1, out + s.substr(0, i), res);
else
helper(s.substr(i), k - 1, out + s.substr(0, i) + ".", res);
}
}
}
}
bool isValid(string s) {
if (s.empty() || s.size() > 3 || (s.size() > 1 && s[0] == '0'))
return false;
int res = atoi(s.c_str());
return res <= 255 && res >= 0;
}
};