算法训练营day29_回溯算法(2.29)
总结
使用erase与unique去重之前需要先对数组进行排序;
树层去重还可以用set,每层设置一个set;
491.递增子序列
需要树层去重;这里不能先排序了,也就不能使用之前的方法了,我干脆全找出来,最后对vector进行去重;
递增的才能进V,这里需要传入last,来得到上一层放的数值大小;
这里没有空集且递增子序列至少为2,所以放ans之前先判断一下;
vector使用erase,unique去重前需要先进行sort,unique会把不同的放到前面,并指向最后一个元素的下一个元素,这样后面一坨就是重复元素,直接erase到end();
**代码随想录的思路不错:**每一层,用一个哈希表set来去重;
class Solution {
public:
vector<int> V;
vector<vector<int>> ans;
void dfs(int u,int last,vector<int> nums){
if(V.size()>=2) ans.push_back(V);
if(u>=nums.size()) return;
for(int i=u;i<nums.size();i++){
int x=nums[i];
if(x>=last){
V.push_back(x);
dfs(i+1,x,nums);
V.pop_back();
}
}
return;
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
V.clear();
ans.clear();
dfs(0,-110,nums);
sort(ans.begin(),ans.end());
ans.erase(unique(ans.begin(),ans.end()),ans.end());
return ans;
}
};
46.全排列
传入的参数是层数,不需要u了(每次都从0开始的)
终止条件就是到最后一层叶子节点的下一层了;
每层遍历扩展0~n-1;
需要树枝去重,加个use标记数组;
class Solution {
public:
vector<int> V;
vector<vector<int>> ans;
void dfs(int cnt,vector<int> nums,vector<bool> st){
if(cnt>=nums.size()){
ans.push_back(V);
return;
}
for(int i=0;i<nums.size();i++){
if(!st[i]){
st[i]=true;
V.push_back(nums[i]);
dfs(cnt+1,nums,st);
V.pop_back();
st[i]=false;
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
V.clear();
ans.clear();
vector<bool> st(nums.size(),false);
dfs(0,nums,st);
return ans;
}
};
47.全排列II
相比于上题还需要树层去重,每层用set去重一下就好了;
class Solution {
public:
vector<int> V;
vector<vector<int>> ans;
void dfs(int cnt,vector<int> nums,vector<bool> st){
if(cnt>=nums.size()){
ans.push_back(V);
return;
}
unordered_set<int> S;
for(int i=0;i<nums.size();i++){
if(S.count(nums[i])) continue;
if(!st[i]){
S.insert(nums[i]);
st[i]=true;
V.push_back(nums[i]);
dfs(cnt+1,nums,st);
V.pop_back();
st[i]=false;
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
V.clear();
ans.clear();
vector<bool> st(nums.size(),false);
dfs(0,nums,st);
return ans;
}
};