原题链接:93. 复原 IP 地址
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你不能重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
示例 1:
输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"]
题解:
题目意思是给一个纯数字的字符串,然后将这个字符串切分成四个新字符串,并且使得每一个新串所表示的整形值处于0-255之间,并且这个新字符串不能有前导0。
那么我们直接枚举切分点的位置,然后判断被切分出来字符串是不是合法的
我们用深度优先搜索,然后枚举点的位置
vAns 用来最后存储结果
vPos 用来存储搜索过程中枚举的点位置
isAvailable 函数用来判断字符串下标从begin-end是否合理
深度优先搜索跳出条件是 已经确定了三个定位点,即vPos.size() == 3
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> vAns;
vector<int> vPos;
dfs(s, vPos, vAns);
return vAns;
}
void dfs(string& str, vector<int>& vPos, vector<string>& vAns){
//pos 当前枚举开始位置
int pos = 0;
if(vPos.size())
pos = vPos[vPos.size()-1] + 1;
//跳出条件
if(vPos.size() == 3){
if(IsAvailable(str, pos, str.length() - 1)){
string ans = "";
ans += str.substr(0, vPos[0] + 1) + ".";
ans += str.substr(vPos[0] + 1, vPos[1] - vPos[0]) + ".";
ans += str.substr(vPos[1] + 1, vPos[2] - vPos[1]) + ".";
ans += str.substr(vPos[2] + 1, str.length() - 1 - vPos[2]);
vAns.push_back(ans);
}
return ;
}
for(int i = pos; i < str.length(); ++i){
if(IsAvailable(str, pos, i)){
vPos.push_back(i);
dfs(str, vPos, vAns);
vPos.pop_back();
}
else{
//当前已经不合理了,直接结束当前分值,算是一个剪枝
return ;
}
}
}
bool IsAvailable(string& str, int begin, int end){
//下标不合法
if(begin < 0 || begin >= str.length() || end < 0 || end >= str.length() || begin > end)
return false;
//字符串长度大于1,判断前导0
if(begin != end && str[begin] == '0')
return false;
//字符串长度不能长于3
if(end - begin + 1 > 3)
return false;
//字符串长度等于3, 判断是否超过255,这里直接用了字符串的比较
if(end - begin + 1 == 3 && str.substr(begin, 3) > "255")
return false;
return true;
}
};