93. 复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 ‘.’ 分隔。
思路
可以使用递归+回溯+剪枝来解决这个问题,首先定义dfs(segId, segStart)表示从字符串s的位置segStart开始搜索字段segId,segId的值可以为0,1,2,3。
递归条件:
- segId的值为4,并且segStart == s.size(),证明已经搜索到一个合法的ip地址,装入结果集。
- segId的值为4,segStart != s.size(),不合法,回溯。
- segId的值不为4,segStart == s.size(),同理不合法,回溯。
- s[segStart]的值为’0’,由于ip地址不能含有前置0,除非该字段的值为0,直接令该字段的值为0,并继续dfs(segId + 1, segStart + 1)。
- 从segStart开始,依次取数,判断数是否在(0, 255]内,在加入字段值数组,进行下一轮dfs。
代码
class Solution {
private:
static constexpr int SEG_COUNT = 4;
vector<int> segment;
vector<string> ans;
public:
void dfs(const string& s, int segId, int segStart) {
//字段值等于4
if(segId == SEG_COUNT) {
//判断是否全部划分
if(segStart == s.size()) {
string tmp = "";
for(int i = 0; i < segId; i++) {
tmp += to_string(segment[i]);
if(i != SEG_COUNT - 1) {
tmp += '.';
}
}
ans.push_back(tmp);
}
return;
}
//字段值不为4,但是全部划分了
if(segStart == s.size()) {
return;
}
//字段首值为0时,只能为0
if(s[segStart] == '0') {
segment[segId] = 0;
dfs(s, segId + 1, segStart + 1);
}
int tmp = 0;
//开始划分字段值
for(int segEnd = segStart; segEnd < s.size(); segEnd++) {
tmp = tmp * 10 + (s[segEnd] - '0');
//划分字段值在(0, 255]内,证明划分成功一个字段值
if(tmp > 0 && tmp <= 0xFF) {
segment[segId] = tmp;
//进入下一dfs划分
dfs(s, segId + 1, segEnd + 1);
}
else {
break;
}
}
}
vector<string> restoreIpAddresses(string s) {
//不合法输入
if(s.size() < 4 || s.size() > 12) {
return ans;
}
segment.resize(SEG_COUNT);
dfs(s, 0, 0);
return ans;
}
};