这道题也是分割问题。但是这道题最后求的是字符串数组,所以可以直接在原字符串上插入逗点。分割的模拟不用多说,用 [startIndex, i] 来模拟分割字符段。当逗点数目达到3时就可以判断递归结束。同时还要实现一个判断字段是否有效的函数。
class Solution{
public:
vector<string> result;
bool isValid(string s, int start, int end){
if(start > end) return false;
if(s[start] == '0' && start != end){
return false;
}
string str = s.substr(start, end - start + 1);
if(stol(str) > 255) return false;
return true;
}
void backtracking(string& s, int startIndex, int pointNums){
if(pointNums == 3){
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, '.'); //将.插入到下标i的字符后面
backtracking(s, i + 2, pointNums + 1); // 插入了一个逗点,所以下一层startIndex要从i+2开始
s.erase(s.begin() + i + 1);
}
else break;
}
}
vector<string> restoreIpAddresses(string s){
result.clear();
if(s.size() < 4 && s.size() > 12) return result;
backtracking(s, 0, 0);
return result;
}
};
这个代码里坑还是挺多的,stoi
函数容易有很多错误,注意 int 型范围。判断合法函数中也要加上start > end
的判断,因为可能逗点添加在字符串的末尾了,导致 start(i+2)比 end 大。
子集问题和一开始组合问题比较相似,原数组中每个元素只能使用一次。但是子集问题需要在递归过程始终记录 path,组合和分割问题只需要在遇到抽象树的叶子节点时才记录 path,因为这两种问题总会有一些条件限制作为递归终止条件。
class Solution{
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex){
result.push_back(path); // 在递归过程中始终记录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();
}
}
vector<vector<int>> subsets(vector<int>& nums){
result.clear();
path.clear();
backtracking(nums, 0);
return result;
}
};
这道题就是重复元素的组合问题向子集问题的迁移,在进行递归回溯前对 nums 进行排序。这里需要注意只在树层去重是不够的,排序在子集问题中是必须的,因为要始终记录 path,不排序只树层去重会在不同树层有重复情况出现。
class Solution{
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex){
result.push_back(path);
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();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums){
result.clear();
path.clear();
sort(nums.begin(), nums.end());
backtracking(nums, 0);
return result;
}
};