这道题是LeetCode里的第40道题。

题目要求:

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

说明:

  • 所有数字(包括目标数)都是正整数。
  • 解集不能包含重复的组合。

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
  [1,2,2],
  [5]
]

解法和第39题几乎一样,区别在于本题每一个数字只能使用一次,但数字在数组中是可以重复的。同样,还是使用回溯剪枝法,先对 candidates 数组元素排序。排序后进行循环递归。具体代码如下:

提交代码:

class Solution {
public:
vector<vector<int>> res;
vector<int> ans;
void getres(vector<int>& candidates,int target,int k,vector<int> ans){
int size=candidates.size();
for(int i=k;i<size;i++){
if(target-candidates[i]>0){
if(i>k&&candidates[i]==candidates[i-1])continue;
ans.push_back(candidates[i]);
getres(candidates,target-candidates[i],i+1,ans);
ans.pop_back();
}
else if(target-candidates[i]<0){return;}
else{
ans.push_back(candidates[i]);
res.push_back(ans);
ans.pop_back();
return;
}
}
return;
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
getres(candidates,target,0,ans);
return res;
}
};

代码和第39题几乎一样,只改了两个地方,第一个是第11行,参数由 i 改为 i+1,这是能想到的确保每一个数字只使用一次的改法。但是这样改还并不完全,因为最终答案会有重复的解答。第二个改法纠结我好久:最笨的想法是先把解保存在一个 set 集合中,然后在转入 vector<vector<int>> 中,但这样太慢了,不想用。那么是什么原因造成解的重复呢?原因就是 candidates 数组中包含着重复数,例如:

示例1:candidates = [10,1,2,7,6,1,5],target = 8,标准解答:[[1,2,5],[1,7],[1,1,6],[2,6]]

没有第九行代码前的解答:[[1,1,6],[1,2,5],[1,7],[1,2,5],[1,7],[2,6]],其中第二个和第四个重复,第三个和第五个重复。因为数组中有两个1,这两个1分别组合了一次,造成了重复。知道原因了,就好解决,首先想到的是加入条件candidates[i]==candidates[i-1]当前后元素相等时,直接跳过本次循环,但问题又来了:[1,1,6]这个解,前后元素相等,但不重复,怎么办?这个我想了好久,最后看评论:因为当前层,如果再取下一个一样的数的话,就会造成重复,但是在下一层加入就不会,因为当前层是替换,如果拿一个一样的替换肯定会重复。再加入条件:i>k 就能保证既不会缺少[1,1,6]这个解,也保证了解的互异。所以第九行加入代码:if(i>k&&candidates[i]==candidates[i-1])continue;,然后剩下的剪枝第39题都有。

提交结果:

个人总结:

本题和第39题不同,难度也体现在最后答案的重复上。回溯法的本质还是递归,递归最难的地方就是容易弄混循环和递归层数,需要画图仔细分析,递归循环是个树图,画图也好容易分析。最后这题也可以不用排序,因为数字只使用一次,但是结果是会有重复的,而且重复的是无规则的,效率低。

【LeetCode】Combination Sum II(组合总和 II)的更多相关文章

  1. [LeetCode] Combination Sum IV 组合之和之四

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  2. [LeetCode] Combination Sum III 组合之和之三

    Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...

  3. 040 Combination Sum II 组合总和 II

    给定候选号码数组 (C) 和目标总和数 (T),找出 C 中候选号码总和为 T 的所有唯一组合.C 中的每个数字只能在组合中使用一次.注意:    所有数字(包括目标)都是正整数.    解决方案集不 ...

  4. Leetcode题库——40.组合总和II

    @author: ZZQ @software: PyCharm @file: combinationSum2.py @time: 2018/11/15 18:38 要求:给定一个数组 candidat ...

  5. 216 Combination Sum III 组合总和 III

    找出所有可能的 k 个数,使其相加之和为 n,只允许使用数字1-9,并且每一种组合中的数字是唯一的.示例 1:输入: k = 3, n = 7输出:[[1,2,4]]示例 2:输入: k = 3, n ...

  6. Leetcode之回溯法专题-40. 组合总和 II(Combination Sum II)

    Leetcode之回溯法专题-40. 组合总和 II(Combination Sum II) 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使 ...

  7. Java实现 LeetCode 40 组合总和 II(二)

    40. 组合总和 II 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在 ...

  8. [LeetCode] 377. Combination Sum IV 组合之和 IV

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  9. 40. 组合总和 II + 递归 + 回溯 + 记录路径

    40. 组合总和 II LeetCode_40 题目描述 题解分析 此题和 39. 组合总和 + 递归 + 回溯 + 存储路径很像,只不过题目修改了一下. 题解的关键是首先将候选数组进行排序,然后记录 ...

随机推荐

  1. SVM为什么需要核函数

    生存?还是毁灭?——哈姆雷特 可分?还是不可分?——支持向量机 之前一直在讨论的线性分类器,器如其名(汗,这是什么说法啊),只能对线性可分的样本做处理.如果提供的样本线性不可分,结果很简单,线性分类器 ...

  2. lnmp.org + phpstorm + xdebug

    lnmp.org下载安装包安装之: lnmp是个集成安装包,就不用自己在配置lnmp环境 安装phpstorm,破解方法:注册服务器为http://idea.lanyus.com 就可以了 xdebu ...

  3. main函数与命令行参数

    main函数的概念 C语言中main函数称之为主函数 一个c程序从main函数开始执行的 下面的main函数定义正确吗? main函数的本质 main函数是操作系统调用的函数 操作系统总是将main函 ...

  4. C/C++ 内存分配方式,堆区,栈区,new/delete/malloc/free

    内存分配方式 内存分配方式有三种: [1] 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量, static 变量. [2] 在栈上创建.在执行函 ...

  5. socket使用非阻塞connect

    在使用tcp的connect调用时,默认是使用阻塞方式,当服务器当前不可用时,connect会等待(内部在重试?)直到超时时间到达,而这个超时时间是系统内核规定的,不能使用setSocketOpt来设 ...

  6. 洛谷 P1774 最接近神的人_NOI导刊2010提高(02)

    题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的 ...

  7. 洛谷 P2126 Mzc家中的男家丁

    题目背景 mzc与djn的…还没有众人皆知,所以我们要来宣传一下. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁,现在mzc要将她们全都聚集起来(干什么就不知道了).现在知道mzc与男家丁们互 ...

  8. UIButton zoomin pressed

    // Scale up on button press - (void) buttonPress:(UIButton*)button { button.transform = CGAffineTran ...

  9. maven打包错误:java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

    Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.118 sec <<< FAILURE! - in ...

  10. html页面编码问题

    今天在项目中碰到需要把已经编码的html页面通过mvc controller返回到前端页面,已编码的html页面包含类似下面的内容: <div style="line-height: ...