给定一个无重复元素的数组 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]
]

递归函数

这里我们新加入三个变量,start 记录当前的递归到的下标,out 为一个解,res 保存所有已经得到的解,每次调用新的递归函数时,此时的 target 要减去当前数组的的数,具体看代码如下:

c++

class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
vector<int> out;
combinationSumDFS(candidates, target, 0, out, res);
return res;
}
void combinationSumDFS(vector<int>& candidates, int target, int start, vector<int>& out, vector<vector<int>>& res) {
if (target < 0) return;
if (target == 0) {res.push_back(out); return;}
for (int i = start; i < candidates.size(); ++i) {
out.push_back(candidates[i]);
combinationSumDFS(candidates, target - candidates[i], i, out, res);
out.pop_back();
}
}
};

递归改进

我们也可以不使用额外的函数,就在一个函数中完成递归,还是要先给数组排序,然后遍历,如果当前数字大于 target,说明肯定无法组成 target,由于排过序,之后的也无法组成 target,直接 break 掉。如果当前数字正好等于 target,则当前单个数字就是一个解,组成一个数组然后放到结果 res 中。

然后将当前位置之后的数组取出来,调用递归函数,注意此时的 target 要减去当前的数字,然后遍历递归结果返回的二维数组,将当前数字加到每一个数组最前面,然后再将每个数组加入结果 res 即可,参见代码如下:

c++

class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
sort(candidates.begin(), candidates.end());
for (int i = 0; i < candidates.size(); ++i) {
if (candidates[i] > target) break;
if (candidates[i] == target) {res.push_back({candidates[i]}); break;}
vector<int> vec = vector<int>(candidates.begin() + i, candidates.end());
vector<vector<int>> tmp = combinationSum(vec, target - candidates[i]);
for (auto a : tmp) {
a.insert(a.begin(), candidates[i]);
res.push_back(a);
}
}
return res;
}
};

java

class Solution {

	List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
if (target <= 0) {res.add(new ArrayList<>());}
//先排序,排序后可以加剪枝
Arrays.sort(candidates);
dfs(new ArrayList<>(), candidates, 0, target, 0);
return res;
} public void dfs(List<Integer> list, int[] candidates, int sum, int target, int start) {
for (int i = start; i < candidates.length; i++) {
list.add(candidates[i]);
if ((sum + candidates[i]) == target) {
//此时tmpList 满足
List<Integer> tmpList = new ArrayList<>(list);
res.add(tmpList);
} if ((sum + candidates[i]) < target) {
dfs(list, candidates, sum + candidates[i], target, i);
} else {
list.remove(list.size() - 1);
//(sum+candidates[i]) > target,因为数组有序,后面一定不满足
break;
}
list.remove(list.size() - 1);
}
}
}

动态规划

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

c++

class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<vector<int>>> dp;
sort(candidates.begin(), candidates.end());
for (int i = 1; i <= target; ++i) {
vector<vector<int>> cur;
for (int j = 0; j < candidates.size(); ++j) {
if (candidates[j] > i) break;
if (candidates[j] == i) {cur.push_back({candidates[j]}); break;}
for (auto a : dp[i - candidates[j] - 1]) {
if (candidates[j] > a[0]) continue;
a.insert(a.begin(), candidates[j]);
cur.push_back(a);
}
}
dp.push_back(cur);
}
return dp[target - 1];
}
};

LeetCode——39. 组合总和的更多相关文章

  1. Java实现 LeetCode 39 组合总和

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

  2. [LeetCode] 39. 组合总和

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

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

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

  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. 组合总和

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

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

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

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

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

随机推荐

  1. 十九 Listener

    Listener 监听器 一 监听器内部原理:其实就是接口回调 需求:A在执行循环,当循环到5的时候,通知B 事先先把某一个对象传递给A ,当A执行到5的时候,通过这个对象来调用B中的方法 但是不是直 ...

  2. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:"text-muted" 类的文本样式

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. PCHMI工控组态开发视频教程

    PCHMI是一款适合所有PLC工程师快速上手工控组态开发的控件 下面是视频教程链接 PCHMI工控组态 02-按钮的使用 PCHMI工控组态 03-数据显示器使用 PCHMI工控组态 04-标签控件的 ...

  4. windows制作动态链接库和使用一

    制作: //myDll.h _declspec(dllexport) int add(int a,int b); _declspec(dllexport) int sub(int a,int b); ...

  5. k8s 各种网络方案【转】

    网络模型有了,如何实现呢? 为了保证网络方案的标准化.扩展性和灵活性,Kubernetes 采用了 Container Networking Interface(CNI)规范. CNI 是由 Core ...

  6. vSphere 计算vMotion的迁移原理

    1. 计算vMotion 的应用场景 1). 计划内停机维护 2). 提高资源的利用率 2. 计算vMotion 需求: 1).共享存储 vMotion需要解决的核心问题就是:将VMs的内存从源ESX ...

  7. 卸载重装ngin的问题解决方案

    1,卸载nginx不保留配置文件 $ sudo apt-get --purge remove nginx 2,卸载自动安装且不再需要的依赖包 $ sudo apt-get autoremove 3,卸 ...

  8. 浅谈Spring 5的响应式编程

    这篇使用Spring 5进行响应式编程的入门文章展示了你现在可以使用的一些新的non-blocking, asynchronous.感谢优锐课老师给予的指导! 近年来,由于响应式编程能够以声明性的方式 ...

  9. git下载安装、配置及idea初始化

    安装 wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.19.0.tar.gz git 安装依赖 yum -y insta ...

  10. ORACLE添加新用户并配置权限 添加其他用户的表权限

    添加用户配置权限 1.查出表空间所在位置 ,file_name from dba_data_files order by file_id; 2.根据步骤1查出的路径.将路径替换掉并指定用户名 路径:D ...