Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

The same repeated number may be chosen from candidates unlimited number of times.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

  1. Input: candidates = [2,3,6,7], target = 7,
  2. A solution set is:
  3. [
  4. [7],
  5. [2,2,3]
  6. ]

Example 2:

  1. Input: candidates = [2,3,5], target = 8,
  2. A solution set is:
  3. [
  4.   [2,2,2,2],
  5.   [2,3,3],
  6.   [3,5]
  7. ]
  

像这种结果要求返回所有符合要求解的题十有八九都是要利用到递归,而且解题的思路都大同小异,相类似的题目有 Path Sum IISubsets IIPermutationsPermutations IICombinations 等等,如果仔细研究这些题目发现都是一个套路,都是需要另写一个递归函数,这里我们新加入三个变量,start 记录当前的递归到的下标,out 为一个解,res 保存所有已经得到的解,每次调用新的递归函数时,此时的 target 要减去当前数组的的数,具体看代码如下:

解法一:

  1. class Solution {
  2. public:
  3. vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
  4. vector<vector<int>> res;
  5. vector<int> out;
  6. combinationSumDFS(candidates, target, , out, res);
  7. return res;
  8. }
  9. void combinationSumDFS(vector<int>& candidates, int target, int start, vector<int>& out, vector<vector<int>>& res) {
  10. if (target < ) return;
  11. if (target == ) {res.push_back(out); return;}
  12. for (int i = start; i < candidates.size(); ++i) {
  13. out.push_back(candidates[i]);
  14. combinationSumDFS(candidates, target - candidates[i], i, out, res);
  15. out.pop_back();
  16. }
  17. }
  18. };

我们也可以不使用额外的函数,就在一个函数中完成递归,还是要先给数组排序,然后遍历,如果当前数字大于 target,说明肯定无法组成 target,由于排过序,之后的也无法组成 target,直接 break 掉。如果当前数字正好等于 target,则当前单个数字就是一个解,组成一个数组然后放到结果 res 中。然后将当前位置之后的数组取出来,调用递归函数,注意此时的 target 要减去当前的数字,然后遍历递归结果返回的二维数组,将当前数字加到每一个数组最前面,然后再将每个数组加入结果 res 即可,参见代码如下:

解法二:

  1. class Solution {
  2. public:
  3. vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
  4. vector<vector<int>> res;
  5. sort(candidates.begin(), candidates.end());
  6. for (int i = ; i < candidates.size(); ++i) {
  7. if (candidates[i] > target) break;
  8. if (candidates[i] == target) {res.push_back({candidates[i]}); break;}
  9. vector<int> vec = vector<int>(candidates.begin() + i, candidates.end());
  10. vector<vector<int>> tmp = combinationSum(vec, target - candidates[i]);
  11. for (auto a : tmp) {
  12. a.insert(a.begin(), candidates[i]);
  13. res.push_back(a);
  14. }
  15. }
  16. return res;
  17. }
  18. };

我们也可以用迭代的解法来做,建立一个三维数组 dp,这里 dp[i] 表示目标数为 i+1 的所有解法集合。这里的i就从1遍历到 target 即可,对于每个i,都新建一个二维数组 cur,然后遍历 candidates 数组,如果遍历到的数字大于i,说明当前及之后的数字都无法组成i,直接 break 掉。否则如果相等,那么把当前数字自己组成一个数组,并且加到 cur 中。否则就遍历 dp[i - candidates[j] - 1] 中的所有数组,如果当前数字大于数组的首元素,则跳过,因为结果要求是要有序的。否则就将当前数字加入数组的开头,并且将数组放入 cur 之中即可,参见代码如下:

解法三:

  1. class Solution {
  2. public:
  3. vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
  4. vector<vector<vector<int>>> dp;
  5. sort(candidates.begin(), candidates.end());
  6. for (int i = ; i <= target; ++i) {
  7. vector<vector<int>> cur;
  8. for (int j = ; j < candidates.size(); ++j) {
  9. if (candidates[j] > i) break;
  10. if (candidates[j] == i) {cur.push_back({candidates[j]}); break;}
  11. for (auto a : dp[i - candidates[j] - ]) {
  12. if (candidates[j] > a[]) continue;
  13. a.insert(a.begin(), candidates[j]);
  14. cur.push_back(a);
  15. }
  16. }
  17. dp.push_back(cur);
  18. }
  19. return dp[target - ];
  20. }
  21. };

Github 同步地址:

https://github.com/grandyang/leetcode/issues/39

类似题目:

Combination Sum III

Combination Sum II

Combination Sum IV

Combinations

Factor Combinations

Letter Combinations of a Phone Number

参考资料:

https://leetcode.com/problems/combination-sum/

https://leetcode.com/problems/combination-sum/discuss/16825/Recursive-java-solution

https://leetcode.com/problems/combination-sum/discuss/16509/Iterative-Java-DP-solution

https://leetcode.com/problems/combination-sum/discuss/16502/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partitioning)

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 39. Combination Sum 组合之和的更多相关文章

  1. [leetcode]39. Combination Sum组合之和

    Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), fin ...

  2. [array] leetcode - 39. Combination Sum - Medium

    leetcode - 39. Combination Sum - Medium descrition Given a set of candidate numbers (C) (without dup ...

  3. leetcode 39. Combination Sum 、40. Combination Sum II 、216. Combination Sum III

    39. Combination Sum 依旧与subsets问题相似,每次选择这个数是否参加到求和中 因为是可以重复的,所以每次递归还是在i上,如果不能重复,就可以变成i+1 class Soluti ...

  4. [LeetCode] Combination Sum 组合之和

    Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C wher ...

  5. LeetCode 39. Combination Sum (组合的和)

    Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique c ...

  6. LeetCode 39 Combination Sum(满足求和等于target的所有组合)

    题目链接: https://leetcode.com/problems/combination-sum/?tab=Description   Problem: 给定数组并且给定一个target,求出所 ...

  7. LeetCode OJ:Combination Sum (组合之和)

    Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C wher ...

  8. 【LeetCode】Combination Sum(组合总和)

    这道题是LeetCode里的第39道题. 题目描述: 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组 ...

  9. leetcode 39 Combination Sum --- java

    Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C wher ...

随机推荐

  1. mybatis的参数传递

    mybatis的参数传递分为两种:1.单参数传递  2.多参数传递 单参数 mybatis会直接取出参数值给Mapper文件赋值 例子如下: 1.Mapper文件内容如下: public void d ...

  2. PHP 中的关于 trait 的简单

    什么是 trait 看看 PHP 官网的介绍. 自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.T ...

  3. 一个利用 Parallel.For 并行处理任务,带有进度条(ProgressBar)的 WinForm 实例(下)

    接着上一篇:一个利用 Parallel.For 并行处理任务,带有进度条(ProgressBar)的 WinForm 实例(上) 直接贴代码了: using System; using System. ...

  4. Kubernetes configMap(配置文件存储)

    Kubernetes configMap(配置文件存储) 官方文档:https://kubernetes.io/docs/tasks/configure-pod-container/configure ...

  5. 『珂朵莉树 Old Driver Tree』

    珂朵莉树 珂朵莉树其实不是树,只是一个借助平衡树实现的数据结构,主要是对于有区间赋值的数据结构题,可以用很暴力的代码很高效地完成任务,当然这是建立在数据随机的基础上的. 即使数据不是随机的,写一个珂朵 ...

  6. App_Code下类无法引用问题

    App_Code 下创建的.cs文件仅仅是“内容”不是代码.设置文件为“编译”就可正常引用.

  7. 大话区块链【Blockchain】

    最近这几天区块链又粉墨登场了,新闻媒体也一直在大量报道,宣称可能要在金融界掀起一番浪潮.甚至有人说很久之前中国就出现了区块链的产物——麻将.那么区块链到底是什么,麻将和区块链又有什么关系呢? 笔者这两 ...

  8. Maven环境搭配及继承

    1. Maven简单介绍 Apache Maven是个项目管理和自动构建工具,基于项目对象模型(POM)的概念. 作用:完成项目的相关操作,如:编译,构建,单元测试,安装,网站生成和基于Maven部署 ...

  9. Google开发者F12工具面板-network详解

    1 开发者工具面板    面板上包含了Elements面板.Console面板.Sources面板.Network面板.Performance面板.Memory面板.Application面板.Sec ...

  10. C/C++中new的使用规则

    本人未重视new与指针的使用,终于,终于在前一天船翻了,而且没有爬上岸: 故此,今特来补全new的用法,及其一些规则: 话不多说 C++提供了一种“动态内存分配”机制,使得程序可以在运行期间,根据实际 ...