题目
给定一个只包含数字的字符串,复原它并返回所有可能的 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 地址。
思考
这一题和leetcode 131. 分割回文串 思考分析很像,都属于利用回溯法分割字符串,所以解法上具有一定相似性。
回溯终止条件
如果逗号已经插入了3次了,观察最后一次插入往后的位置,观察剩下来的字符串能否构成合法字符串。
如果能构成,那么将s装入结果;
如果不能构成,回溯到上一个阶段。
//如果逗号数量为3,判断第四个子区间是否合法,如果合法就放入结果中
if(point_nums==3)
{if(isValid(s,startindex,s.size()-1)){result.push_back(s);}return;
}
回溯逻辑
1、这里利用逗号来进行分割,在原string上进行操作。如果startindex~i之间的字符串合法的话,我们就在i后面插入一个逗号。
然后对逗号后面的字符串进行回溯遍历。不满足的回溯组合将把逗号消除,完成回撤。
for(int i=startindex;i<s.size();i++)
{//子串区间:[startindex,i]if(isValid(s,startindex,i)) //判断子串区间的子串是否合法{s.insert(s.begin()+i+1,'.'); //在i后面插入一个逗号point_nums++;backtracking(s,i+2); //切割过的字符不能再次被切割,插入逗号之后下一个子串的起始位置发生往后移动1//回溯撤销point_nums--;s.erase(s.begin()+i+1); //回溯删除逗号}//不合法的子串直接结束本层循环,只要一个子串不合法,结果就是不合法的else break;
}
2、考察字符串是否合法:
//判断字符串s[start,end]组成的数字是否合法
bool isValid(const string& s,int start,int end)
{if(start>end) return false;if(s[start]=='0' && start!=end) //0开头的数字不合法{return false;}int num=0;for(int i=start;i<=end;i++){if(s[i]>'9' ||s[i]<'0')//遇到非数字字符不合法{return false;}num =num*10+(s[i]-'0');if(num>255) return false;}return true;
}
完整代码
class Solution {
public:vector<string> result;int point_nums=0;//判断字符串s[start,end]组成的数字是否合法bool isValid(const string& s,int start,int end){if(start>end) return false;if(s[start]=='0' && start!=end) //0开头的数字不合法{return false;}int num=0;for(int i=start;i<=end;i++){if(s[i]>'9' ||s[i]<'0')//遇到非数字字符不合法{return false;}num =num*10+(s[i]-'0');if(num>255) return false;}return true;}//这里直接对s进行修改void backtracking(string& s,int startindex){//如果逗号数量为3,判断第四个子区间是否合法,如果合法就放入结果中if(point_nums==3){if(isValid(s,startindex,s.size()-1)){result.push_back(s);}return;}for(int i=startindex;i<s.size();i++){//子串区间:[startindex,i]if(isValid(s,startindex,i)) //判断子串区间的子串是否合法{s.insert(s.begin()+i+1,'.'); //在i后面插入一个逗号point_nums++;backtracking(s,i+2); //切割过的字符不能再次被切割,插入逗号之后下一个子串的起始位置发生往后移动1//回溯撤销point_nums--;s.erase(s.begin()+i+1); //回溯删除逗号}//不合法的子串直接结束本层循环,只要一个子串不合法,结果就是不合法的else break;}}vector<string> restoreIpAddresses(string s) {result.clear();point_nums=0;backtracking(s,0);return result;}
};