题目描述:

给定一个数组 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. Swift与OC的相互调用

    Swift经过四年的发展已经趋于成熟,是时候学一下了,感谢公司swift大佬的不吝赐教.心有所感记录一下,如有不足欢迎指正批评. 新建swift项目 新建Swift.OC类文件 可在新建OC文件时,建 ...

  2. 使用mybatis提供的各种标签方法实现动态拼接Sql。这里演示where标签和if标签实现使用姓名的模糊查询和性别查询用户列表,当用户没有选择姓名以及性别时查询出所有的记录。

    1.需求: 使用姓名的模糊查询和性别查询用户列表,当用户没有选择姓名以及性别时查询出所有的记录. 2.在UserMapper接口中定义方法: public List<User> findU ...

  3. android studio打包apk

    转载:http://chenfeicqq.iteye.com/blog/1889160 1)Android Studio菜单Build->Generate Signed APK      (2) ...

  4. Laravel中Trait的用法实例详解

    本文实例讲述了Laravel中Trait的用法.分享给大家供大家参考,具体如下: 看看PHP官方手册对Trait的定义: 自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 trait ...

  5. 8.3 mysql 表操作

    库操作 一 系统数据库 information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列信息.权限信息.字符信息等    performance_sch ...

  6. HDU 1569 方格取数(2) (最小割)

    方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  7. Web数据挖掘综述

     

  8. Oracle EBS学习网站列表

    Oracle官方文档库http://tahiti.oracle.com/http://www.oracle.com/technetwork/documentation/index.html#apps其 ...

  9. SQL Server关于存储过程的一点简单使用心得

    ===========================创建无参无返回值的存储过程===========================create proc pro_nameas--要执行的sql语句 ...

  10. LoadRunner监控SQLServer

    监控SQLSERVER时,能增加度量.但是只有系统资源相关的度量有数据,而和sqlserver相关的度量却没有数据. 解决方法: 改为在System Resource Graphs中通过添加Windo ...