题目:
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)
思路:回溯法。需要注意的几个地方:一是当trace是大小大于4,可以直接剪枝。二是结束条件的判断,当pos的值大于string的长度时,必然是冗余项。这是因为在调用递归的时候,并没有进行边界检查,string的substr函数当超出结尾时也是有效的。这就造成了冗余项。例如,192.168.1.1,当pos到了最后一个1时,会调用3次递归函数,使得pos分别为8,9,10. 虽然后面两种情况超出范围了,但是substr函数还是会返回1,这样就会产生3个一样的结果。因此,当pos的值大于string长度时,必然是冗余项,直接返回。
class Solution {
public:
vector<string> trace;
bool is_valid(const string& s) {
if (s.size() == 1) return s >= "0" && s <= "9";
else if (s.size() == 2) return s >= "10" && s <= "99";
else if (s.size() == 3) return s >= "100" && s <= "255";
else return false;
}
void restore_helper(const string& s, int pos, vector<string>& result) {
if (trace.size() > 4) return; //pruning
if (pos > (int)s.size()) return; //duplicated
if (pos == (int)s.size()) { //reach the end
if (trace.size() == 4) { //legal
string new_ip;
for (int i = 0; i < (int)trace.size(); ++i) {
new_ip.append(trace[i]);
if (i < (int)trace.size() - 1) {
new_ip.append(".");
}
}
result.push_back(new_ip);
return;
} else { //illegal
return;
}
}
for (int len = 1; len <= 3; ++len) {
if (is_valid(s.substr(pos, len))) {
trace.push_back(s.substr(pos, len));
restore_helper(s, pos + len, result);
trace.pop_back();
}
}
}
vector<string> restoreIpAddresses(string s) {
vector<string> result;
restore_helper(s, 0, result);
return result;
}
};
总结:复杂度为O(n).