【LeetCode】Combination Sum II(组合总和 II)
这道题是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)的更多相关文章
- [LeetCode] Combination Sum IV 组合之和之四
Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...
- [LeetCode] Combination Sum III 组合之和之三
Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...
- 040 Combination Sum II 组合总和 II
给定候选号码数组 (C) 和目标总和数 (T),找出 C 中候选号码总和为 T 的所有唯一组合.C 中的每个数字只能在组合中使用一次.注意: 所有数字(包括目标)都是正整数. 解决方案集不 ...
- Leetcode题库——40.组合总和II
@author: ZZQ @software: PyCharm @file: combinationSum2.py @time: 2018/11/15 18:38 要求:给定一个数组 candidat ...
- 216 Combination Sum III 组合总和 III
找出所有可能的 k 个数,使其相加之和为 n,只允许使用数字1-9,并且每一种组合中的数字是唯一的.示例 1:输入: k = 3, n = 7输出:[[1,2,4]]示例 2:输入: k = 3, n ...
- Leetcode之回溯法专题-40. 组合总和 II(Combination Sum II)
Leetcode之回溯法专题-40. 组合总和 II(Combination Sum II) 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使 ...
- Java实现 LeetCode 40 组合总和 II(二)
40. 组合总和 II 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在 ...
- [LeetCode] 377. Combination Sum IV 组合之和 IV
Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...
- 40. 组合总和 II + 递归 + 回溯 + 记录路径
40. 组合总和 II LeetCode_40 题目描述 题解分析 此题和 39. 组合总和 + 递归 + 回溯 + 存储路径很像,只不过题目修改了一下. 题解的关键是首先将候选数组进行排序,然后记录 ...
随机推荐
- 【详解】JS中的作用域、闭包和回收机制
在讲解主要内容之前,我们先来看看JS的解析顺序,我们惯性地觉得JS是从上往下执行的,所以我们要用一个变量来首先声明它,来看下面这段代码: alert(a); var a = 1; 大家觉得这段代码有什 ...
- java.lang.IllegalArgumentException: name MUST NOT NULL! at org.nutz.dao.impl.NutDao.fetch
Nutz传值报错问题 作者:Vashon 时间:20150902 平台:Nutz框架 Java后台方法中拿值时报的错 报错信息: java.lang.IllegalArgumentException: ...
- sql中保留2位小数
问题: 数据库里的 float momey 类型,都会精确到多位小数.但有时候 我们不需要那么精确,例如,只精确到两位有效数字. 解决: 1. 使用 Round() 函数,如 Round(@num,2 ...
- 洛谷 P1363 幻想迷宫
题目描述 背景 Background (喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫.) WD:呜呜,肿么办啊…… LHX:momo...我们一定能走 ...
- Exception in thread "main" java.lang.NoSuchMethodError: org.apache.http.entity.ContentType.withCharset(Ljava/lang/String;)Lorg/apache/http/entity/ContentType;
解决方案是:第一点先检查一下使用的包是否冲突,是否是版本号一致.第二点是增加一个包 忙活了好久才解决了这个异常,小小的激动一下啊啊
- 算法马拉松13 A-E解题报告
A题意(取余最长路): 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱乐值为所经过的位置的权的总和. 有一天,她被下了恶毒的诅咒,这个诅咒的作用是将她的 ...
- fgetc, fgets, getc, getchar, gets, ungetc - 输入字符和字符串
总览 (SYNOPSIS) #include <stdio.h> int fgetc(FILE *stream); char *fgets(char *s, int size, FILE ...
- pytest生成测试报告
生成JunitXML格式的测试报告 --junitxml=report\h.xml 生成result log 格式的测试报告 --resultlog=report\h.log 生成htm ...
- c++ 各种类型字符串转换
typedef std::string u8string; u8string To_UTF8(const std::u16string &s) { std::wstring_convert&l ...
- perl 引用(数组和hash引用) --- perlreftut - Mark 的一个简单的'引用'教程 ---Understand References Today. --Mark Jason Dominus, Plover Systems (mjd-perl-ref+@plover.com)
https://blog.csdn.net/fangwei1235/article/details/8570886 首页 博客 学院 下载 论坛 APP 问答 商城 活动 VIP会员 招聘 ITeye ...