这道题是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. P1281 书的复制

    题目描述 现在要把m本有顺序的书分给k给人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一.第三.第四本书给同一个人抄写. ...

  2. Spring-打印机案例

    1.导包 <!--beans--><dependency> <groupId>org.springframework</groupId> <art ...

  3. TCP简单程序

    服务器段: package com.dcz.socket; import java.io.IOException; import java.io.OutputStream; import java.n ...

  4. WORD操作的问题

    最近有个小项目主要是对文档,特别是WORD的操作,读取表格数据存到数据库: 再把数据库的数据读出来写入WORD,下载下来,诸如此类的东西,说来很是简单. 想了想是用什么开发呢? C#常用的,没话说,也 ...

  5. Web开发入门不得不看章

    引 如今,各种互联网的Web应用程序层出不穷,那么如何快速入门,成长为一个优秀的Web开发工作者呢? 这个问题不容易回答,几乎所有的培训机构都不能清晰地解答. 所以对于Web开发刚刚入门的菜鸟们,我觉 ...

  6. Oracle Data Integrator 12c 安装(ODI安装)

    Oracle Data Integrator 12c 安装(ODI安装) 企业版安装步骤(包含独立安装步骤) 官网下载Oracle Data Integrator 12cR2 (12.2.1.0.0) ...

  7. JS 一个页面关闭多个页面

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><meta ...

  8. c#将本地文件上传至服务器(内网)

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. 在Windows 10删除百度云盘的盘符

    1点击微软图标不放,然后点击R  打开运行命令 2输入  Regedit  进入注册表 3找到以下路径:HKEY_LOCAL_MACHINE  SOFTWARE  Microsoft  Windows ...

  10. centos中安装elasticsearch5.0

    1.安装jdk 可以直接安装自带的openjdk,安装完成之后修改一下java的环境变量.另一种方式是就是安装oracle的jdk,从官网上下载http://www.oracle.com/techne ...