题目描述:

给定一个数组 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]
]

要完成的函数:

vector<vector<int>> combinationSum2(vector<int>& candidates, int target)

说明:

1、这道题给定一个vector,里面装着几个正整数,正整数可以是重复的,还给了一个正整数的target。

要求找出所有组合,使得每个组合中的正整数的和等于target。

不能重复使用某一个数。

每个组合以一维vector的形式存储,最终所有组合存储在二维vector中,返回二维vector。

2、举个例子,[10,1,2,7,6,1,5],target是8,我们人类是怎么解决这道题的?

第一个数10,不满足。

第二个数1,可以,但我们还需要7,第三个数2,可以,但我们还需要5,第四个数7不行,第五个数6不行,第六个数1可以,但我们还需要4,第七个数5不行。

然后我们回退到第六个数,我们不要1了,我们还需要5,试探第七个数5,刚好可以。[1,2,5]

接着再回退一步,我们不要第三个数2了,这时候我们还要7,试探第四个数7,刚好可以。[1,7]

接着再回退一步,我们不要第四个数7了,这时候我们还需要7,试探第五个数6,可以,我们还需要1,试探第六个数1,刚好可以。[1,6,1]

接着再回退一步,我们不要第六个数1,我们还需要1,试探第七个数5,不可以,结束。

接着再回退一步……

你会发现这就是一个不断试探的过程,这种题我们适合用递归来做。

要求每个数只能使用一次,这个也简单,我们递归的时候,起始index设置在下一个就好了。

但我们还没有解决重复组合的问题,比如[2,5,2,1,2],target是5。

如果我们用递归来做,我们会得到[2,2,1],[2,1,2],[5],[2,1,2]这样的组合。

对待重复这件事,排序有奇效。

我们简单排个序,变成[1,2,2,2,5],同样递归来做,得到[1,2,2],我们看到下一个数跟当前数是一样的,那么再往前走一步,试探5,就不要试探第三个2了。

这样可以快速地解决重复组合的问题。

代码如下:(附详解)

    vector<vector<int>>res;//全局变量,最终要返回的二维vector
vector<int>res1;//全局变量,存储每次可能的组合
void digui(vector<int>& candidates,int index,int target,vector<int>& res1)
{
if(target==0)//满足退出条件
{
res.push_back(res1);//每个组合插入到res中
return;//返回到上一层递归
}
while(index<candidates.size())//不断地试探
{
if(candidates[index]<=target)
{
res1.push_back(candidates[index]);//进入递归前,设置好res1
digui(candidates,index+1,target-candidates[index],res1);
res1.pop_back();//退出递归后,恢复res1
}
else//如果发现candidates[index]大于target了,那么不要再试了,直接返回到上一层的递归
return;
while(candidates[index]==candidates[index+1])//想要更新index,如果下一个值跟当前值一样,不断地往前走
index++;
index++;
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
{
sort(candidates.begin(),candidates.end());//排个序,升序
digui(candidates,0,target,res1);//直接进入递归
return res;//最终返回res
}

上述代码实测8ms,beats 98.51% of cpp submissions。

对于这个过程还不太清晰的同学,可以自己手工推导一下所有过程,逻辑会清晰很多。

也可以参考博主上一篇博文leetcode-39-组合总和(有趣的递归),可以说是同个类型的题目。

leetcode-40-组合总和 II的更多相关文章

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

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

  2. LeetCode 40. 组合总和 II(Combination Sum II)

    题目描述 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能 ...

  3. leetcode 40. 组合总和 II (python)

    给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. ...

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

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

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

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

  6. 40组合总和II

    题目:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合.candidates 中的每个数字在每个组合中只能使用一 ...

  7. LeetCode 中级 - 组合总和II(105)

    给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. ...

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

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

  9. 40. 组合总和 II leetcode JAVA

    题目: 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使 ...

  10. 40. 组合总和 II

    题目描述: 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只 ...

随机推荐

  1. for 续3

    --------siwuxie095                 (三)delims=xxx (xxx 是被定义的符号,该符号在文本中存在,将作为分隔符)     定义分隔符(用于切分文本)   ...

  2. Visual Studio工具 vcpkg简介

    博客参考: https://blog.csdn.net/cjmqas/article/details/79282847#43-%E7%A7%BB%E9%99%A4%E5%85%A8%E5%B1%80% ...

  3. Windows本地Linux虚拟机ping不通的解决办法

    解决办法:启动虚拟机双网卡支持: 网卡1:Host-Only网络 网卡2:NAT网络 设置好以后,可以在Linux主机中ifconfig查看本地Host-Only的网络地址,与电脑中的地址应该是同一网 ...

  4. DART: a fast and accurate RNA-seq mapper with a partitioning strategy DART:使用分区策略的快速准确的RNA-seq映射器

    DART: a fast and accurate RNA-seq mapper with a partitioning strategyDART:使用分区策略的快速准确的RNA-seq映射器 Abs ...

  5. [Training Video - 1] [Introduction to Web services]

    What is a web service? http://webservicex.net/ws/default.aspx WebService是一种跨编程语言和跨操作系统平台的远程调用技术. 跨编程 ...

  6. 自旋构造(更新)c#

    int x; void MultiplyXBy (int factor) { var spinWait = new SpinWait(); while (true) { int snapshot1 = ...

  7. rabbitmq用户权限管理

    原文地址: http://my.oschina.net/hncscwc/blog/262246 安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号 ...

  8. Redis数据结构(三)

    Redis五种数据类型: (1)字符串 (2)字符串列表 (3)有序字符串集合 (4)哈希 (5)字符串集合 其中(4)(5)应用最多. key命名的注意: (1)不要过长,尽量不要超过1024,会降 ...

  9. thinkphp5 swoole 执行异步任务

    目录结构: 服务器端: <?php /* *author:hdj */ namespace app\Console; use think\console\Command; use think\c ...

  10. 使用Intel的FPGA电源设计FPGA 供电的常用反馈电阻阻值

    使用Intel的FPGA电源设计FPGA 供电的常用反馈电阻阻值. 当前仅总结使用EN5339芯片的方案 Vout = Ra*0.6/Rb + 0.6 芯片手册推荐Ra取348K,则 3.3V时,取R ...