LeetCode - 解题笔记 - 93 - Restore IP Addresses
Solution 1
一开始我以为是动态规划,后来反应过来要求输出所有的结果,那就必须要搜索了。
终止策略有:
- 已经有4个满足要求的分段,所有的数字分配完毕,找到一个答案
- 已经有4个满足要求的分段,尚有数字未分配,非有效答案(这一步可以直接替代超长字符串剪枝)
- 不足4个满足要求的分段,但所有数字分配完毕,非有效答案
搜索策略有:
- 如果当前向下搜索,第一个数字为0,那么只能将当前位作为一个分段向下搜索
- 否则,可以不断包括后续数字,直到和超过255(相对于硬性搜索三位,直接这么判断更简洁)
-
时间复杂度: O ( 3 4 × 12 ) O(3^4 imes 12) O(34×12),原则来看搜索复杂度应该是 O ( N ! ) O(N!) O(N!)的,但是因为这道题的限制范围非常严格(最多检查12位,只能是4个分段),所以搜索深度只有4层,每层枚举量最多为3。 空间复杂度: O ( 1 ) O(1) O(1),不考虑最终答案的占用,中间仅维护常数个状态量
class Solution { public: vector<string> restoreIpAddresses(string s) { vector<string> ans; vector<int> segments; this->dfs(ans, segments, s, 0); return ans; } private: void dfs(vector<string> & ans, vector<int> & segments, string & s, int pos) { if (segments.size() == 4) { if (pos == s.size()) { ans.emplace_back(this->makeIPAddress(segments)); } return; } if (pos == s.size()) { return; } if (s[pos] == 0) { segments.push_back(0); this->dfs(ans, segments, s, pos + 1); segments.pop_back(); } else { int segment = 0; for (int offset = pos; offset < s.size(); offset++) { segment = segment * 10 + (s[offset] - 48); if (segment < 256) { segments.push_back(segment); this->dfs(ans, segments, s, offset + 1); segments.pop_back(); } else { break; } } } } string makeIPAddress(vector<int> & segments) { string ans; for (int i = 0; i < segments.size(); i++) { ans += to_string(segments[i]); if (i < segments.size() - 1) { ans += .; } } return ans; } };
Solution 2
Solution 1的Python实现
class Solution: def restoreIpAddresses(self, s: str) -> List[str]: ans = list() segments = list() def dfs(pos): nonlocal segments, ans if len(segments) == 4: if pos == len(s): ans.append(..join(segments)) return if pos == len(s): return if s[pos] == 0 : segments.append(0) dfs(pos + 1) segments.pop() else: for offset in range(pos, len(s)): if int(s[pos:offset + 1]) < 256: segments.append(s[pos:offset + 1]) dfs(offset + 1) segments.pop() else: break dfs(0) return ans