难度:中等
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 '.'
分隔。
示例:
输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]
题目分析:
回溯法,得将字符串分成四个部分,每个部分要满足条件。
结束条件:n == 4,然后进行res存储
all station:使用for循环,i = 1,
传入参数为n+1(仅作为计数器),剪枝(val>255 或者 i!=to_string(val).size()开头为0)
参考代码:
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
string ip;
vector<string> res;
back_search(res,0,s,ip);
return res;
}
void back_search(vector<string>& res, int n, string s, string ip)
{
if(n == 4)
{
if(s.empty())
res.push_back(ip);
}else{
for(int i = 1; i < 4; i++)
{
if(s.size() < i) //字符串分完了,后面没得分了,就返回
break;
int temp = stoi(s.substr(0,i));//将字符串转换为数字
if(temp > 255 || i != std::to_string(temp).size())//temp大于255或者开头为0均为无效IP
break;
back_search(res,n+1,s.substr(i),ip + s.substr(0,i)+(n==3 ? "" : "."));
}
}
}
};
参考代码:(上面代码有点骚气,看看这个版本)
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
if (s.empty() || s.size() < 4)
return res;
string temp;
back_search(s, res, temp, 0);
return res;
}
void back_search(string s, vector<string>& res, string temp, int count)
{
//结束条件
if (count == 4)
{
if (!s.empty())//如果还有剩余的字符串,说明没分完,就不压入res中
return;
temp.pop_back();//去掉最后一个‘.’,因为是值引用,所以不影响回溯
res.push_back(temp);
return;
}
//all station
for (int i = 1; i < 4; i++)
{
if (i <= s.size())//不让i越界,如果一共只有4个字符,每个位置分三个字符也不现实
{
string str = s.substr(0, i);//将0~i的子串提取出来
int data = stoi(str);//换算成数字,方便下面条件判断
//如果有两个及以上的字符,开头是不能为0的,也不能超过255(IP划分规则)
//不满足规则的,直接返回
if (str[0] == '0' && str.size() > 1 || data > 255)
return;
//把字符串和‘.’存储起来
temp += str;
temp.push_back('.');
back_search(s.substr(i), res, temp, count + 1);//递归并计数
for (int j = 0; j < str.size() + 1; j++)//字符串不能一次性pop
temp.pop_back();
}
}
}
};