方法一:递归+回溯
题设可知,IP地址是由四段数字组成的数字序列,中间使用“.”连接起来,每段数字处于[0, 255]之间。所以我们可以将问题分解为:得到上一段数字后,从余下的字符串求剩余几段的数字。
1、从字符串的起点开始,得到第一段数字,由题设可知,每一段的数字都不会超过三位数,所以遍历前三个数字;
2、下一段数字从上一段数字的后一位开始向后遍历,递归得到所有的可能性。通过对每段数字进行有效性判断,四段数字都满足有效性的是有效的IP地址,存入数组中。
时间复杂度:o(3n)
空间复杂度:o(n)
class Solution {
private:
// 存储所有可能的IP地址
vector<string> res;
// 可能的IP地址
string nums;
public:
vector<string> restoreIpAddresses(string s) {
// 特殊情况处理
if (s.length() < 4)
return res;
dfs(s, 0, 0);
return res;
}
void dfs(string s, int step, int idx) {
// 存储当前段的字符
string cur = "";
if (step == 4) {
if (idx == s.length())
res.push_back(nums);
else
return;
} else {
for (int i = idx; i < idx + 3 && idx < s.length(); i++) {
// 记录便于后续回溯
string temp = nums;
cur += s[i];
int num = stoi(cur);
// 数字在有效范围内且前置不能有多个0
if (num <= 255 && (cur.length() == 1 || cur[0] != '0')) {
if (step != 3)
nums += cur + ".";
else
nums += cur;
// 递归得到下一段的IP
dfs(s, step + 1, i + 1);
// 回溯
nums = temp;
}
}
}
}
};
方法二:暴力迭代
暴力迭代,遍历所有的可能性将字符串分为四段数字,每段数字都符合IP地址的有效性的压入数组。
class Solution {
private:
vector<string> res;
public:
vector<string> restoreIpAddresses(string s) {
// 特殊情况处理
if (s.length() < 4)
return res;
string nums1, nums2, nums3, nums4;
// 循环三次,遍历所有可能
for (int i = 0; i < 3 && i < s.length() - 3; i++) {
for (int j = i + 1; j < i + 4 && j < s.length() - 2; j++) {
for (int k = j + 1; k < j + 4 && k < s.length() - 1; k++) {
nums1 = s.substr(0, i + 1);
nums2 = s.substr(i + 1, j - i);
nums3 = s.substr(j + 1, k - j);
nums4 = s.substr(k + 1, s.length() - k - 1);
if ((stoi(nums1) <= 255 && (nums1.length() == 1 || nums1[0] != '0')) &&
(stoi(nums2) <= 255 && (nums2.length() == 1 || nums2[0] != '0')) &&
(stoi(nums3) <= 255 && (nums3.length() == 1 || nums3[0] != '0')) &&
(stoi(nums4) <= 255 && (nums4.length() == 1 || nums4[0] != '0'))) {
res.push_back(nums1 + "." + nums2 + "." + nums3 + "." + nums4);
}
}
}
}
return res;
}
};

京公网安备 11010502036488号