题目描述:

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。

示例 1:

输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]

示例 2:

输入: candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

要完成的函数:

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

说明:

1、这道题给定一个vector,里面装着彼此不重复的元素,元素是正整数,还给了一个target,也是正整数。

要求找出各种有可能的组合,使得vector中的元素的和等于target。

每个组合存储在一个一维的vector中,最终把这些一维的vector存在二维的vector中,返回二维vector。

各个组合不能重复。

2、我们先来看一个例子,vector是[2,3,6,7],target是7,我们人类怎么解决这个问题呢?

我们当然是从后面看起,最大的7,看能不能满足target,结果是可以的,那么我们再看前一个数6。

6小于等于7,我们还要一个1,往本身或者前面看有没有小于等于1的,结果没有,那么我们就没有办法搭配6了,我们再看前一个数3。

3小于等于7,我们还要4,本身还可以再减去3,那么还要一个1,再往本身或者前面看,没有1。

那我们也许可以不要第二次减去3,我们减去前一个数2,然后还要一个2,刚好本身可以满足。

然后再看前一个数2,本身还可以再减去2,然后本身还可以再减去2,然后还要一个1,但没有办法了。

所以最终我们得到的组合是[[7],[3,2,2]]。

做的题目比较多的同学,可能已经嗅到了一股递归的味道。

这道题就是要不断试探,试探可以满足target的,插入到二维vector中,试探到不可以满足的,回退一步,再试其他可能。

代码如下:(附详解)

    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);//存储到二维vector中
return;
}
while(index>=0)//不断地试探
{
if(candidates[index]<=target)//如果可以减去
{
res1.push_back(candidates[index]);//进入递归前,设置一下res
digui(candidates,index,target-candidates[index],res1);
res1.pop_back();//退出递归,恢复一下res
}
index--;//index-1,试探前一个数值
}
if(index<=0)//如果index==-1,那么只能返回了
return; }
vector<vector<int>> combinationSum(vector<int>& candidates, int target)
{
int s1=candidates.size();
digui(candidates,s1-1,target,res1);//直接进入递归
return res;
}

上述代码在递归那个部分,可能有些同学还不太清晰,可以自己手写一下推导的过程,逻辑会更加清晰。

【 再啰嗦两句,理解逻辑的同学可以不用看了】

其实vector比如[2,3,6,7],我们可以粗略地看成外层的递归和内层的递归。外层递归比如第一次试探了7,刚刚好。

接着循环迭代到前一个数6,可以减去,然后进入内层递归,不能再减去本身6了,所以循环迭代到前一个数3,也还是不能,所以循环迭代到前一个数2,也还是不能,然后结束内层递归。

接着循环迭代到前一个数3,可以减去,然后进入内层递归,可以减去本身3,再进入深一层的内层递归,不能再减去3了,循环迭代到前一个数2,也不能,结束深一层的内层递归,返回内层递归,我们不减去3,直接减去2,进入深一层的内层递归,可以减去本身2,那么结束深一层的内层递归,同时vector到头部了,结束内层递归。

接着循环迭代到前一个数2,可以减去,然后进入内层递归,可以减去本身2,进入深一层的内层递归,可以减去本身2,进入再深一层的内层递归,不能再减去2了,于是退出再深一层的内层递归,再退出深一层的内层递归,再退出内层递归。

接着……前面没有数了,结束外层递归。

我们会发现其实外层递归和内层递归的处理逻辑是一样的,都是不断地试探,所以我们可以统一写成一种形式。

上述代码实测12ms,beats 98.16% of cpp submissions。

leetcode-39-组合总和(有趣的递归)的更多相关文章

  1. [leetcode] 39. 组合总和(Java)(dfs、递归、回溯)

    39. 组合总和 直接暴力思路,用dfs+回溯枚举所有可能组合情况.难点在于每个数可取无数次. 我的枚举思路是: 外层枚举答案数组的长度,即枚举解中的数字个数,从1个开始,到target/ min(c ...

  2. Java实现 LeetCode 39 组合总和

    39. 组合总和 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字 ...

  3. [LeetCode] 39. 组合总和

    题目链接 : https://leetcode-cn.com/problems/combination-sum/ 题目描述: 给定一个无重复元素的数组 candidates 和一个目标数 target ...

  4. leetcode 39 组合总和 JAVA

    题目: 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制 ...

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

    题目描述 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限 ...

  6. leetcode 39. 组合总和(python)

    给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制重复被选 ...

  7. LeetCode——39. 组合总和

    给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制重复被选 ...

  8. 【LeetCode】39. 组合总和

    39. 组合总和 知识点:递归:回溯:组合:剪枝 题目描述 给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数  ...

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

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

  10. Leetcode 377.组合总和IV

    组合总和IV 给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数. 示例: nums = [1, 2, 3] target = 4 所有可能的组合为: (1, 1, 1, ...

随机推荐

  1. for 续2

    --------siwuxie095             (二)skip=n 忽略(屏蔽.隐藏)文本前 N 行的内容. (N 必须大于 0,不能等于 0)     格式: FOR /F " ...

  2. 和大于S的最小子数组 · Minimum Size Subarray Sum

    [抄题]: 给定一个由 n 个正整数组成的数组和一个正整数 s ,请找出该数组中满足其和 ≥ s 的最小长度子数组.如果无解,则返回 -1. 给定数组 [2,3,1,2,4,3] 和 s = 7, 子 ...

  3. Golang学习系列:(一)介绍和安装

    Golang学习系列:(一)介绍和安装 Java程序员带你来到Go的世界,让我们开始探索吧! Go是一种新的语言,一种并发的,带有垃圾回收的.快速编译的语言,它具有一下特点: 他可以在一台计算机上用几 ...

  4. PCL 3维点云的模板匹配

    Doc 来自PCL官方文档 http://www.pointclouds.org/documentation/tutorials/template_alignment.php#template-ali ...

  5. Struts2,Spring3,Hibernate4整合--SSH框架

    Struts2,Spring3,Hibernate4整合--SSH框架(学习中) 一.包的导入 1.Spring包 2.Hibernate 包 3.struts 包 (还欠 struts2-sprin ...

  6. [Java] Java API文档下载方法

    Java API文档下载方法:http://jingyan.baidu.com/article/a3aad71ac9e48fb1fb009692.html Oracle : http://www.or ...

  7. Jenkins 邮箱配置及问题解决

    Failed to send out e-mail javax.mail.MessagingException: Could not connect to SMTP host: smtp.rytong ...

  8. Git 客户端基本配置

    Welcome to Git (version -preview20140611) Run 'git help git' to display the help index. Run 'git hel ...

  9. Ubuntu的常识使用了解4

    寻找文件的「名称」 在Linux系统当中,文件的数量非常非常的多, 需要使用查找工具来高效查找指定文件位置:

  10. SqlServer获取字符串中数字,中文及字符部分数据

    --获取英文字符数据 Create function [dbo].[Fun_GetChar] ( ) ) ) AS BEGIN BEGIN ,'') --删掉一个非数字的字符,循环结束,剩余的为数字部 ...