复原IP地址
题目描述
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 '.' 分隔。
示例
输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]
递归方法
需要找出所有可能复原的IP地址,因此可以考虑使用递归的方法,对所有可能的字符串分割方法进行搜索,并筛选出满足要求的作为答案
假设题目中给出的字符串为s,使用递归函数dfs(segId,segStart)表示从s[segStart]的位置开始,搜索IP地址中的第segId段,其中segId∈{0,1,2,3,}。由于IP字段都为0-255的整数,因此从segStart开始,从小到大依次枚举当前这一段IP地址的阶数位置segEnd。如果满足要求,就递归的进行下一段搜索,调用递归函数dfs[segId+1,segEnd+1].
特殊情况
由于IP地址的每一段不能有前导0,如果s[segStart]等于字符0,那么IP地址的第segId段只能为0
在递归搜索的过程中,如果已经得到了全部的4段ip地址(即segId= 4),并且遍历完了整个字符串(即segStart= |s|,其中|s|表示字符串s的长度),那么此时就是要求的答案之一,将其加入答案。在其他时刻,如果提前遍历完了字符串,需要结束遍历,回溯到上一步。
class Solution {
private:
static constexpr int SEG_COUNT = 4;
private:
vector<string> ans;
vector<int> segments;
public:
void dfs(const string &s,int segId,int segStart)
{
//如果找到了4段ip,并遍历完了字符串,那就是一种答案
if(segId == SEG_COUNT)
{
if(segStart == s.size())
{
string ipAddr;
for(int i = 0;i < SEG_COUNT;i++)
{
ipAddr += to_string(segments[i]);
if(i != SEG_COUNT-1)
{
ipAddr +=".";
}
}
ans.push_back(move(ipAddr));
}
return ;
}
//如果还没有找到4段ip地址就遍历完了字符串,那么提前回撤
if(segStart == s.size())
{
return;
}
//由于不能有前导0,如果当前数字为0,那么这段IP地址只能为0
if(s[segStart] =='0')
{
segments[segId] = 0;
dfs(s,segId+1,segStart+1);
}
//一般情况
int addr = 0;
for(int segEnd = segStart;segEnd < s.size();segEnd++)
{
addr = addr * 10 + (s[segEnd]-'0');
if(addr > 0 && addr <= 0xFF)
{
segments[segId] = addr;
dfs(s,segId+1,segEnd+1);
}
else
{
break;
}
}
}
vector<string> restoreIpAddresses(string s) {
segments.resize(SEG_COUNT);
dfs(s,0,0);
return ans;
}
};
知识小讲堂:
C++ 11 std::move()
是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝,它就是为性能而生
c++ to_string()
功能就是将数值转换成字符串,返回对应的字符串
vector容器的resize()方法
作用是改变vector容器中元素的数目
vector容器的reserve()方法
作用是设置容器的容量