首页 > 其他分享 >【力扣】组合总和3(组合的去重)

【力扣】组合总和3(组合的去重)

时间:2024-03-07 21:44:05浏览次数:20  
标签:used target 组合 int 力扣 vector candidates path 总和

问题描述


注意,如果数组里有两个元素的值相同,那么这两个元素是可以出现在同一个组合里的:
image
但是:如果按前面的思路分析的话,会发现结果中出现很多相同的组合。
像这样:
image
这很明显是由于两个相同的1造成的,因为当前的startindex对应第一个1时,向下一层递归后,starindex定位的还是1,。
image
如果用这种方法,在录入结果时剔除重复的结果,则有可能在某些极端的样例里造成超时。
问题在于,我们在跳过多余的1时,要注意只能在同层枚举时跳过,如果在向下递归时跳过,就会忽略1,1,6这个组合,并且在跳过时只能跳过后面的重复元素,否则也得不到1,1,6
得到这样的处理方式
image
每一个循环代表一层的逐个枚举,每一个递归调用代表向下一层的深入
一定要注意哪里是水平的,哪里是垂直的。
代码如下:

class Solution {
public:
    vector<vector<int> > res;
    vector<int> path;
    void backtrace(vector<int>& candidates, int target, int startindex){
	if(accumulate(path.begin(), path.end(),0) >= target){
	//if(accumulate(path) >= target){
		if(accumulate(path.begin(), path.end(),0) == target){
			// for(int i = 0; i < res.size(); i++){
			// 	if(path == res[i]){
			// 		return ;
			// 	}
			// }
			res.push_back(path);
		}
		return ;
	}
	
	for(int i = startindex; i < candidates.size(); i++){
        if(i != startindex && (candidates[i] == candidates[i - 1])){
			//cout<<"遇到了第二个1"<<endl;
			continue;
		}
		path.push_back(candidates[i]);
//		int gap = 1;
//		while(candidates[i+gap] == candidates[i]){
//			gap++;
//		}
		backtrace(candidates, target, i + 1);
		path.pop_back();
	}
}//void 
vector<vector<int> > combinationSum2(vector<int>& candidates, int target) {
    res.clear();
	path.clear();
	sort(candidates.begin(), candidates.end());
	backtrace(candidates, target, 0);
	return res; 
}
};

再看一下代码随想录的思路:

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int>& candidates, int target, int sum, int startIndex, vector<bool>& used) {
        if (sum == target) {
            result.push_back(path);
            return;
        }
        for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {
            // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
            // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
            // 要对同一树层使用过的元素进行跳过
            if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {
                continue;
            }
            sum += candidates[i];
            path.push_back(candidates[i]);
            used[i] = true;
            backtracking(candidates, target, sum, i + 1, used); // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次
            used[i] = false;
            sum -= candidates[i];
            path.pop_back();
        }
    }

public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<bool> used(candidates.size(), false);
        path.clear();
        result.clear();
        // 首先把给candidates排序,让其相同的元素都挨在一起。
        sort(candidates.begin(), candidates.end());
        backtracking(candidates, target, 0, 0, used);
        return result;
    }
};

思路可以说基本一样,只不过他跳过同层重复元素的处理方式不一样,用了一个used数组记录状态。

标签:used,target,组合,int,力扣,vector,candidates,path,总和
From: https://www.cnblogs.com/satsuki26681534/p/18059756

相关文章

  • 216. 组合总和 IIIc
    /***Returnanarrayofarraysofsize*returnSize.*Thesizesofthearraysarereturnedas*returnColumnSizesarray.*Note:Bothreturnedarrayand*columnSizesarraymustbemalloced,assumecallercallsfree().*/inttemp[10];voiddfs(int**......
  • 77. 组合C
    回溯其实就是抽象图的遍历过程这题数据实在太离谱了。/***Returnanarrayofarraysofsize*returnSize.*Thesizesofthearraysarereturnedas*returnColumnSizesarray.*Note:Bothreturnedarrayand*columnSizesarraymustbemalloced,assumecaller......
  • 【力扣】组合总数(回溯法)
    题目描述#include<iostream>#include<vector>usingnamespacestd;vector<vector<int>>res;vector<int>path;intaccumulate(vector<int>path){ intsum; for(inti=0;i<path.size();i++){ sum+=path[i]; } r......
  • 【力扣】电话号码的组合(回溯法)
    问题描述classSolution{public:vector<string>res;stringpath;//charA[26]={'a','b','c','d','e','f','g',//'h','i','j','k&......
  • 卡农 -- HNOI2011 -- DP&组合
    卡农--\(HNOI2011\)$$luogu$$$$HZOI$$题意给定一个集合$A={1\lex\len|x}$,求出其\(m\)个不相同的且不为空集的子集,使得第\(i\)个元素的在所有选出的子集中出现的次数\(appear_i\mod2=0\)题解首先一个已知结论:对于一个\(A\)这样的集合,他......
  • 【力扣】求组合(回溯算法)
    题目描述2.以下是回溯算法的模版classSolution{private:vector<vector<int>>res;vector<int>path;//这个变量名还是设为path更合适voidbacktrace(intn,intk,intstartindex){//递归结束条件,这个是根据问题要求修改的if(path.s......
  • 初三组合恒等式和二项式定理练习 题解
    A.多项式推柿子:\[\begin{aligned}&\sum\limits_{k=0}^{n}b_{k}(x-t)^{k}\\=&\sum\limits_{k=0}^{n}b_{k}\sum\limits_{i=0}^{k}\binom{k}{i}x^{i}(-t)^{k-i}\\=&\sum\limits_{0\leqslanti\leqslantk\leqslantn}\binom{k}{i}b_{......
  • 力扣T26与T27的区别
    T27给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。T26你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一......
  • 【RS】Sentinel-2哨兵二号数据预处理(大气校正、重采样、波段组合)
    ​    刚分享过新版欧空局的数据下载教程,正好把哨兵2号预处理的教程也分享一下,主要就是使用官方插件Sen2or对L1C级数据进行大气校正,使用SNAP软件对L2A级数据进行重采样并导出ENVI可以打开的格式,最后使用ENVI对重采样后的数据进行波段组合,以便于后期的定量分析。1.软件......
  • 【力扣】括号匹配(栈的应用)
    题目描述顾名思义代码如下:#include<iostream>#include<string>#include<stack>usingnamespacestd;boolisValid(strings){ if(s.empty()){ returntrue; } if(s.size()%2!=0){ returnfalse; } inti=0; stack<char>st; while(i<......