93.复原IP地址
这道题还是非常难的。在本题里我们并没有使用path数组,因为可以在原字符串上进行划分,但是每次加上点后要进行回溯操作。这道题和切割文字串特别像,都是切割字串的问题,这种切割字串的问题需要在for循环里进行条件判断,而不是每一个i都存在一个分支,注意判定好切割条件。
class Solution {
public:
vector<string> result;
vector<string> restoreIpAddresses(string s) {
backtracking(s,0,0);
return result;
}
bool isvalue(string s,int start,int end)
{
if(start>end)
return false;
if(s[start]=='0'&&start!=end)
return false;
int sum=0;
for(int i=start;i<=end;i++)
{
sum=sum*10+s[i]-'0';
if(sum>255)
return false;
}
return true;
}
void backtracking(string s,int index,int pointnum)
{
if(pointnum==3)
{
if(isvalue(s,index,s.size()-1))
{
result.push_back(s);
}
return ;
}
for(int i=index;i<s.size();i++)
{
if(isvalue(s,index,i))
{
s.insert(s.begin()+i+1,'.');
pointnum++;
backtracking(s,i+2,pointnum);
pointnum--;
s.erase(s.begin()+i+1);
}
else
break;
}
}
};
78.子集
集合求子集的回溯算法和组合问题的回溯算法的最大区别是集合问题的回溯算法树状图上每一个节点都需要保留结果。所以我们就在backtracking里边一开始就保留结果这样也能够照顾到空集的情况。
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
vector<vector<int>> subsets(vector<int>& nums) {
backtracking(nums,0);
return result;
}
void backtracking(vector<int> nums,int index)
{
result.push_back(path);
if(index>=nums.size())
return ;
for(int i=index;i<nums.size();i++)
{
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
};
90.子集II
就是求子集问题加上了去重复的思想,判定一下是同层去重复就好了。
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<bool> used(nums.size(),false);
sort(nums.begin(),nums.end());
backtracking(used,0,nums);
return result;
}
void backtracking(vector<bool> used,int index,vector<int> nums)
{
result.push_back(path);
if(index>=nums.size())
return;
for(int i=index;i<nums.size();i++)
{
if(i!=0&&nums[i]==nums[i-1]&&used[i-1]==false)
continue;
path.push_back(nums[i]);
used[i]=true;
backtracking(used,i+1,nums);
path.pop_back();
used[i]=false;
}
}
};