【LeetCode-回溯】复原IP地址
题目描述
给定一个只包含数字的字符串,复原它并返回所有可能的 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 = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
输入:s = "0000"
输出:["0.0.0.0"]
输入:s = "1111"
输出:["1.1.1.1"]
题目链接: https://leetcode-cn.com/problems/restore-ip-addresses/
思路
使用回溯来做。使用一个数组 curAns 来保存输入的字符串被切分的子串。如果 curAns.size()==4,则说明我们找到了一个答案,然后将数组 curAns 中的子串使用.
连接起来即可。
还有一个需要注意的地方就是剪枝,使用以下三种方法就可以在运行时间上超过 100% 的结果:
- 如果当前子串 ss 长度大于 1,且 ss[0]=='0',则返回。例如,ss=="021";
- 如果当前子串 ss 长度大于 1,且 ss 对应的数字大于 255,则返回。例如,ss=="266";
- 如果当前结果 curAns 的长度大于 4,则返回。因为 ip 地址只有 4 段,curAns 长度大于 4,说明不是一个正确的切割。
代码如下:
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
if(s.empty() || s.size()<4 || s.size()>12) return {};
vector<string> curAns;
vector<string> ans;
dfs(s, 0, curAns, ans);
return ans;
}
void dfs(string& s, int start, vector<string> curAns, vector<string>& ans){
if(start>=s.size() && curAns.size()==4){
string temp = "";
for(int i=0; i<curAns.size(); i++){
if(i==0) temp += curAns[i];
else temp += "." + curAns[i];
}
ans.push_back(temp);
return;
}
for(int i=start; i<s.size(); i++){
string ss = s.substr(start, i-start+1);
if(ss.size()>1 && ss[0]=='0') return; // 剪枝 1
if(ss.size()>1 && stoi(ss)>255) return; // 剪枝 2
curAns.push_back(ss);
if(curAns.size()>4) return; // 剪枝 3
dfs(s, i+1, curAns, ans);
curAns.pop_back();
}
}
};
使用一个数组来保存切割的子串,在符合条件时,将数组中的子串用.
连接放进答案中是一个很好的想法,能简化代码的写法。这个想法来自这篇题解。