算法思想转自力扣题解diocletian(作者),仅用于个人学习
复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 ‘.’ 分隔。
示例:
输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]
题解:
题目中需要使用string类中的substr函数来截取字符串:substr是C++语言函数,主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。
问题的有一个坑:数字0是否出现在IP地址首,如果出现那么这个IP地址失效。
使用回溯法穷举(有点暴力破解的意思,时间复杂程度为O(n^4)),并不进行总位数的判断。
思路很简单:穷举并判断,在开始的时候我们不需要关注他有多少位第一个点前面应该有几位数,因为数字最多是三位,所以首先取2、25、255,首先进行第一个数字的判断,2满足0<2<255,加点然后从5开始,又分为三种情况5、55、552,后面处理和之前相同。
采用递归实现,递归返回条件有三:
1、点的数量达到4个(因为最后一组数的后面还会加一个点,在放入容器之前会去掉),但是没有到达字符串末尾,此方案失败。
2、点的数量没有达到4个,但是到达字符串末尾,此方案失败。
3、点的数量到达四个,同时到达字符串末尾,此方案成功,入容器。
class Solution {
vector<string> ans;//存放最终结果
int n;//要修复字符串的长度
string result;//表示回溯中当前已经拼起来的字符串
int num_dot;//result中点的个数
int idx;//用来表示当前已经截取到s的位置
public:
//判断当前数字是否在合法范围内0~255
bool check(string x)
{
int m = stoi(x);
return m >= 0 && m <= 255;
}
void backtrack(string& s)
{
//递归终止条件
if (num_dot == 4 && idx >= n)
{//如果刚好凑齐4个“.”号,而且s遍历完毕。result删掉最后一个点号后加入答案。
ans.push_back(result.substr(0, result.size() - 1));
return;
}
//否则如果遍历完了,也没凑齐4个".",说明不能构成合法IP
else if (idx >= n && num_dot < 4)return;
//或者没有遍历完,但已经超过4个"."了,不能构成合法IP
else if (idx <= n - 1 && num_dot >= 4)return;
//否则,可以继续往result后面加1位,2位或者3位。需要考虑2个问题:有没有这么多位,以及是不是0开头
vector<string> strs;//result后面能加哪些
for (int i = 0; i < 3 && idx + i < n;++i)
{//第i个候选者,长度为i+1
string candidate = s.substr(idx, i + 1);
//注意如果长度为2或者3的时候,第1位不能为0.
if (i != 0 && candidate[0] == '0')continue;
//否则加入strs中
strs.push_back(candidate);
}
//对strs里面每一种可行方案,遍历,回溯
for (int i = 0;i < strs.size();++i)
{
if (check(strs[i]))//判断数字是否合法
{
//判断传入的字符串长度
int len = strs[i].size();
//将字符串与result进行拼接并且在后面加点
result += (strs[i] + ".");
//点个数加1
num_dot++;
//已经截取s位置的下一个位置,即还未截取的第一个位置
idx += len;
//递归,将后面还未截取的重新截取
backtrack(s);
//重置result,num_dot,idx,准备迎接下一个strs[i]
result = result.substr(0, result.size() - len - 1);
num_dot--;
idx -= len;
}
}
return;
}
vector<string> restoreIpAddresses(string s) {
//初始化
ans.clear();
n = s.size();
idx = 0;//已汲取s的长度
num_dot = 0;//点的个数
result = "";//回溯过程中拼好的字符串
backtrack(s);
return ans;
}
};