题目如下:
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example:
Given "25525511135",
return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)
分析如下:
收到上一道DFS + backtracking的题目 palindrome partitioning的影响,在思考这道题目如何做dfs和back tracking ,实验了多个版本,最后总是遇到各种错误。最后网上搜到一个巧妙的做法。来自Yu's coding garden. 代码和解释都如下:
我的代码:
/*
Input: "010010"
Output: ["0.1.0.10","0.1.0.10","0.1.1.0","0.10.0.10","0.10.1.0","0.100.1.0","1.0.0.10","1.0.1.0","1.0.1.0","10.0.1.0"]
Expected: ["0.10.0.10","0.100.1.0"]
这个错例说明切分的分部的首位不能为0。
*/
//受到palindrome题目的影响,我一开始想到的是使用DFS + backtracking把所有可能的分割方案都算出来,然后过滤,或者一边算一边剪纸,但是这样code的结构会比较复杂了。
//这个做法比较巧妙的地方是,观察到了ip只能被分成4个部分,所以用k from 0 to 4来控制循环。这样切分到了第4块之后,如果还有剩余字符串,那么就说明当前切分方案失败,及时剪枝。
class Solution {
public:
bool isValid(string s ) {
if (s.length()==3 && (atoi(s.c_str()) > 255 || atoi(s.c_str())==0)) return false;
if (s.length()==3 && s[0] == '0') return false;
if (s.length()==2 && atoi(s.c_str()) ==0) return false;
if (s.length()==2 && s[0] == '0') return false;
return true;
}
void getRes(string s, string every, vector<string> &result, int k) {
//因为这里k先定了dfs,所以直接用string 型 every而不是string & every,所以是传值型的参数而非传引用型的参数,所以也省去了backtracking。
if (k==0) {
if (s.empty())
result.push_back(every);
return;
}else {
for (int i =1 ; i<=3; ++i) {
if (s.size() >= i && isValid(s.substr(0, i))) {
if (k==1)
getRes(s.substr(i), every + s.substr(0, i), result, k-1);
else
getRes(s.substr(i), every + s.substr(0, i) + ".", result, k-1);
}
}
}
}
vector<string> restoreIpAddresses(string s) {
vector<string> result;
getRes(s, "", result, 4);
return result;
}
};
参考资料: