两区别的dfs:
都是每个值只能使用一次,和为目标值不用使用全部。
和为目标值,会根据有序的元素不同开头进行dfs
所有序列,需要对每一个元素进行dfs,还要标记是否访问。
对于重复元素需要判断同一层的dfs 重复元素 只需要dfs一次需要判断。
- 加起来和为目标值的组合
输入:
[100,10,20,70,60,10,50],80
返回值:
[[10,10,60],[10,20,50],[10,70],[20,60]]
说明:
给定的候选数集是[100,10,20,70,60,10,50],目标数是80
class Solution {
vector<int> vis;
public:
vector<vector<int> > permuteUnique(vector<int> &num) {
// 数组所有排列 搜索 第一个n种 第二个n-1种。。。采用标记数组标记,重复使用的不用重新遍历
vector<vector<int> > res;
vector<int> per;
vis.resize(num.size());
sort(num.begin(), num.end());
dfs(num, per, res, 0);
return res;
}
void dfs(vector<int> &num, vector<int> &per, vector<vector<int>> &res, int idx){
if(idx == num.size()){
res.push_back(per);
return;
}
for(int i=0; i<num.size();i++){
if(vis[i] || i>0 && num[i]==num[i-1] && !vis[i-1]){
continue; // visited 不能使用, 且 重复的元素第一个dfs后以后重复的元素不需要dfs
}
per.push_back(num[i]);
vis[i]=1; // 标记访问过
dfs(num, per, res, idx+1); //
vis[i]=0;
per.pop_back();
}
}
};
- 有重复项数字的所有排列
输入
[1,1,2]
输出
[[1,1,2],[1,2,1],[2,1,1]]
class Solution {
public:
vector<vector<int> >ans;
vector<vector<int> > combinationSum2(vector<int> &num, int target) {
// 和目标 为 target所有组合 搜索
// visited
vector<int> tmp;
sort(num.begin(), num.end());
dfs(num, 0, target, tmp);
return ans;
}
void dfs(vector<int> &num, int start, int target, vector<int> &tmp){
if(target == 0) {ans.push_back(tmp); return;}
int len = num.size();
if(target < 0 || start>=num.size()) return ; // 剪纸
for(int i=start; i<len; i++){ // 不需要每个都用
if(i>start && num[i] == num[i-1]) continue; // 去重复元素
tmp.push_back(num[i]);
dfs(num, i+1, target-num[i], tmp);
tmp.pop_back();
}
}
};