对于这种暴搜出不来的就该用回溯了。对于一个合理的IP地址:有四个字串,每个字串的值的和在[0, 255]中即可(注意不可有前导0)。所以我们用一个计数器pointSum为给定字符串中分割字串的分隔符'.'计数。每当有一个合理的子串时在该子串后面增加一个分隔符,当pointSum等于3时该字符串合理。
- class Solution {
- private:
- vector
result; - void backtracking(string& s, int startIndex, int pointSum) {
- // pointSum 是IP地址中合理分割的分隔符
- if (pointSum == 3) { // 三个分隔符四个部分是正常的IP地址
- if (isValid(s, startIndex, s.size() - 1)) // 判断区间为左闭右闭
- {
- result.push_back(s); // 放入结果集
- }
- return ;
- }
- for (int i = startIndex; i < s.size(); i++) {
- // 单层循环逻辑
- if (isValid(s, startIndex, i)) {
- s.insert(s.begin() + i + 1, '.'); // 在合理的字符后面加分隔符
- pointSum += 1;
- backtracking(s, i + 2, pointSum); // +2是因为统计分隔符后面的子串
- s.erase(s.begin() + i + 1); // 回溯1:删除分隔符
- pointSum -= 1; // 回溯2:统计器-1复原
- }
- else break;
- }
- }
- // 判断子串是否在[0, 255]范围内
- bool isValid(const string& s, int begin, int end) {
- if (begin > end) return false;
- if (s[begin] == '0' && begin != end) return false;
- // 有前导0不合法
- int num = 0;
- for (int i = begin; i <= end; i++) {
- if (s[i] > '9' || s[i] < '0') return false;
- num = num * 10 + (s[i] - '0');
- if (num > 255) return false;
- }
-
- return true;
- }
- public:
- vector
restoreIpAddresses(string s) { - backtracking(s, 0, 0);
- return result;
- }
- };
emm……蛮有难度的一个题。题意很好懂,思路也容易理,但是不大好写,我改了蛮久。
标标准准的回溯题,类似于之前的组合。遇到合理的路径加入最终结果集,回溯弹出即可。代码如下:
- class Solution {
- private:
- vector
int>> result; - vector<int> path;
- void backtracking(vector<int>& s, int startIndex) {
- result.push_back(path);
- if (path.size() > s.size()) return ;
- for (int i = startIndex; i < s.size(); i++) {
- path.push_back(s[i]);
- backtracking(s, i + 1);
- path.pop_back();
- }
- }
- public:
- vector
int>> subsets(vector<int>& nums) { - backtracking(nums, 0);
- return result;
- }
- };