方法:回溯
- 类似131. 分割回文串循环中 [startIndex, i] 这个区间就是截取的子串,需要判断这个子串是否合法。如果合法就在字符串后面加上符号.表示已经分割
- 接下来调用递归函数时是i+2,因为多加了个‘.’,且递归深度只有3层
- for循环内如果不合法就break结束本层循环,不是131的continue
class Solution {
private:
vector<string> ret;
bool isValid(const string& s, int start, int end) {
if (start > end) return false;
if (s[start] == '0' && start != end) return false;
int num = 0;
for (int i = start; i <= end; i++) {
num = num * 10 + (s[i] - '0');
if (num > 255) return false;
}
return true;
}
void backtracking(string& s, int startIndex, int pointNum) {
if (pointNum == 3) {
if (isValid(s, startIndex, s.size() - 1)) ret.push_back(s);
return;
}
for (int i = startIndex; i < s.size(); i++) {
if (isValid(s, startIndex, i)) {
s.insert(s.begin() + i + 1, '.');
backtracking(s, i + 2, pointNum + 1);
s.erase(s.begin() + i + 1);
} else
break;
}
}
public:
vector<string> restoreIpAddresses(string s) {
if (s.size() < 4 || s.size() > 12) return ret;
backtracking(s, 0, 0);
return ret;
}
};
方法:回溯
- 和组合问题一样,{2,1}和{1,2}是一个,没有排序,所以需要startIndex
- 遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合
- 求取子集问题,不需要任何剪枝,因为子集就是要遍历整棵树
class Solution {
private:
vector<int> path;
vector<vector<int>> ret;
void backtracking(vector<int>& nums, int startIndex) {
ret.push_back(path);
if (startIndex >= nums.size()) return;
for (int i = startIndex; i < nums.size(); i++) {
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
backtracking(nums, 0);
return ret;
}
};
方法:回溯
class Solution {
private:
vector<int> path;
vector<vector<int>> ret;
void backtracking(vector<int>& nums, int startIndex) {
ret.push_back(path);
if (startIndex >= nums.size()) return;
for (int i = startIndex; i < nums.size(); i++) {
if (i != startIndex && nums[i] == nums[i - 1]) continue;
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
backtracking(nums, 0);
return ret;
}
};