回溯模板
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表);
回溯,撤销处理结果
}
}
- lc216. 组合总和3:有个条件写错了,找了半天,草
- lc17. 电话号码的字母组合:每次回溯的集合不一样
- lc39. 组合总和:(可以重复,索引可以选当前的)
- lc40. 组合总和2:unordered_set<vector< int >>不行,没有针对vector的hash
检验了对深度递归和宽度遍历的理解,感觉挺好
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
void backtrack(int target,int add,vector<int>& candidates,int index)
{
if(add==target)
{
ans.push_back(temp);
return;
}
for(int i=index;i<candidates.size()&&add+candidates[i]<=target;i++)
{
if(i>index&&candidates[i]==candidates[i-1])
{
continue;
}
temp.push_back(candidates[i]);
add+=candidates[i];
backtrack(target,add,candidates,i+1);
temp.pop_back();
add-=candidates[i];
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
backtrack( target, 0, candidates, 0);
return ans;
}
};
class Solution {
public:
vector<string> ans;
void backtrack(string &s,int index,int pointnum)
{
if(pointnum==3)
{
if(isyes(s,index,s.size()-1))
{
ans.push_back(s);
}
return;
}
for(int i=index;i<s.size();i++)
{
if(isyes(s,index,i))
{
s.insert(s.begin()+i+1,'.');
pointnum++;
backtrack(s, i+2,pointnum);
s.erase(s.begin()+i+1);
pointnum--;
}
else{
break;
}
}
}
bool isyes(string s,int begin,int end)
{
if(begin>end) return false;
else if(s[begin]=='0'&&begin!=end) return false;
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;
}
vector<string> restoreIpAddresses(string s) {
if(s.size()<4||s.size()>12) return ans;
backtrack(s, 0, 0);
return ans;
}
};
- lc78. 子集
- lc90. 子集2
- lc491. 递增子序列:全是陷阱,题意就弄错了,4767里467竟然也算…(还以为必须要连续的)
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
void backtrack(int index,vector<int>& nums)
{
if(temp.size()>=2)
{
ans.push_back(temp);
}
int uset[201]={0};
for(int i=index;i<nums.size();i++)
{
if((!temp.empty()&&nums[i]<temp.back())||uset[nums[i]+100]==1)
{
continue;
}
uset[nums[i]+100]=1;
temp.push_back(nums[i]);
backtrack(i+1, nums);
temp.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtrack(0,nums);
return ans;
}
};
- lc46. 全排列:用used数组检测用没用过
- lc47. 全排列2:利用排序,同时要注意是同一树层还是同一树枝,据此进行去重判断
class Solution {
public:
vector<vector<int>>ans;
vector<int> temp;
int pre;
void backtrack(vector<int>&nums,vector<bool>&judge)
{
if(temp.size()==nums.size())
{
ans.push_back(temp);
return;
}
for(int i=0;i<nums.size();i++)
{
if(i>0&&nums[i]==nums[i-1]&&judge[i-1]==false)
{
continue;
}
if(judge[i]==false)
{
judge[i]=true;
temp.push_back(nums[i]);
backtrack(nums,judge);
temp.pop_back();
judge[i]=false;
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool>judge(nums.size(),false);
sort(nums.begin(),nums.end());
backtrack(nums,judge);
return ans;
}
};
- lc332. 重新安排行程:unordered_map<string,map<string,int>>
- lc51. N皇后:一行一行的回溯
- lc37. 解数独:双层递归