题目描述:

给定一个无重复元素的数组 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. 37-python中bs4获取的标签中如何提取子标签

    如果只是要提取一个标签 里面的属性值啥的,直接看这篇文章就可以了: 23-python用BeautifulSoup用抓取a标签内所有数据 如果是标签的嵌套,可以参考下面的思路,虽然不是很简洁,但是可以 ...

  2. Java程序设计10——与运行环境交互

    本部分介绍一些与运行环境相关的类 Sun为Java提供了丰富的基础类库,Java SE有三千多个基础类,要多敲代码,多练. 1.main()方法解析 如果一个程序总是按规定的流程运行,无需处理用户动作 ...

  3. DB2日期转格式化字符串

    DB2  应该有个  TO_CHAR  的函数. 用来把 日期 转换为 字符串 1 2 3 4 5 6 7 8 9 10 db2 => SELECT db2 (cont.) =>   TO ...

  4. vue项目 调用百度地图 BMap is not defined

    这次老板新接了一个四点半官网页面,使用vue来写.emm……我感觉整个人都不好了,两天半解决了20个静态页面.还好vue写页面简直飞快,遇到一个vue的新坑,使用百度地图. 研究了好一会,总是报错BM ...

  5. HDU 1071 The area (数学定积分)

    题意:求阴影部分面积. 析:没什么可说的,就是一个普通的定积分. 代码如下: #include <cstdio> #include <iostream> using names ...

  6. 看图说说Sun HotSpot虚拟机对象

  7. linux数据库备份

    linux数据库备份 服务端启用二进制日志 如果日志没有启开,必须启用binlog,要重启mysql,首先,关闭mysql,打开/etc/my.cnf,加入以下几行: [mysqld] log-bin ...

  8. 在MyEclipse中怎么修改Servlet模板

    原Servlet模板实例 package www.csdn.net.servlet; import java.io.IOException; import java.io.PrintWriter; i ...

  9. 深海划水队项目---七天冲刺day1

    团队会议: 团队成员的任务认领安排: 张兆敏:登录界面,游戏界面(包含游戏区.控制区.显示信息区). 乐滔:方块的形状.移动(向左或者向右)旋转(顺时针或者逆时针),方块的下落(包含硬着陆和软着陆), ...

  10. Android-有序广播是可以中断的

    在之前的博客,Android-广播概念,中介绍了(广播和广播接收者)可以组件与组件之间进行通讯,有两种类型的广播(无序广播 和 有序广播),这篇博客就来讲解有序广播的代码实现: 有序广播:接收者 可以 ...