93. 复原 IP 地址
思路
类似回文串分割,每次分割都要判定现在分割的[startIndex, i]
是否为合法的。
代码
class Solution {
public:
vector<string> res;
vector<string> restoreIpAddresses(string s) {
backtracking(s, 0, 0);
return res;
}
void backtracking(string s, int startIndex, int nums){
if (nums >= 3){
if (isValid(s, startIndex, s.size() - 1))
res.push_back(s);
return;
}
for (int i = startIndex; i < s.size(); i ++){
if (isValid(s, startIndex, i)){
s.insert(s.begin() + i + 1, '.');
nums ++;
backtracking(s, i + 2, nums);
nums --;
s.erase(s.begin() + i + 1);
}
}
}
bool isValid(string s, int start, int end){
if (start > end || end - start >= 3) return false;
if (s[start] == '0' && start != end) return false;
int num = 0;
for (int i = start; i <= end; i ++){
num *= 10;
num += s[i] - '0';
}
// cout << num << endl;
if (num > 255) return false;
return true;
}
};
78. 子集
思路
与全排列的区别是在于只要是子集就可以放到结果里,所以要更改放入res
的条件
代码
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> subsets(vector<int>& nums) {
res.push_back(path);
backtracking(nums, 0);
return res;
}
void backtracking(vector<int>& nums, int startIndex){
if (!path.empty()){
res.push_back(path);
if (path.size() == nums.size()) return;
}
for (int i = startIndex; i < nums.size(); i ++){
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
};
90. 子集 II
思路
与上题区别在于,会存在重复数字,也就是说树的同一层数字只能出现一次,所以使用set
删除重复的
代码
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
res.push_back(path);
backtracking(nums, 0);
return res;
}
void backtracking(vector<int>& nums, int startIndex){
if (!path.empty()){
res.push_back(path);
if (path.size() == nums.size()) return;
}
unordered_set<int> uset;
for (int i = startIndex; i < nums.size(); i ++){
if (uset.find(nums[i]) != uset.end()) continue;
path.push_back(nums[i]);
uset.insert(nums[i]);
backtracking(nums, i + 1);
// uset.erase(nums[i]);
path.pop_back();
}
}
};