LeetCode39.组合总和
题目描述
/**
* 给定一个无重复元素的数组 candidates 和一个目标数 target ,
* 找出 candidates 中所有可以使数字和为 target 的组合。
* <p>
* candidates 中的数字可以无限制重复被选取。
* <p>
* 说明:
* <p>
* 所有数字(包括 target)都是正整数。
* 解集不能包含重复的组合。
*/
思路分析
- 可以使用递归 + 回溯的思路
- 使用一个深度优先的递归函数,遍历候选数组,每次取出一个元素,就将这个元素添加到队列中,因为数组中的数字可以无限制的被选取,因此下一次从数组中选取数字时依旧从第一个元素开始选取
- 当以第一个元素作为起点的所有情况都遍历完毕后,然后遍历以第二个元素开头的所有情况,形成递归
- 若当前路径下所有元素的和等于target,说明找到一条路径,记录到结果集,如果所有元素的和小于target,说明已经不在满足条件,直接返回
- 源码见下
源码及分析
/**
*
* @param candidates 候选数组
* @param target 目标值
* @return 返回结果集
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
//数组长度
int len = candidates.length;
//结果集
List<List<Integer>> res = new ArrayList<>();
//保存每次递归的结果路径
Deque<Integer> path = new ArrayDeque<>();
//递归 + 回溯
dfs(candidates, 0, len, target, path, res);
return res;
}
/**
* @param candidate 候选数组
* @param begin 每次搜索开始的位置
* @param len 数组长度
* @param target 目标值
* @param path 找到的路径
* @param res 结果集
*/
public void dfs(int[] candidate, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {
//System.out.println(path);
//如果搜索到target小于 0 ,说明没有找到,直接返回
if (target < 0) {
return;
}
//如果搜索到target 等于 0,说明找到一个路径,保存到结果集
if (target == 0) {
res.add(new ArrayList<>(path));
return;
}
for (int i = begin; i < len; i++) {
//将当前路径保存
path.addLast(candidate[i]);
//递归 + 回溯
dfs(candidate, i, len, target - candidate[i], path, res);
//状态重置
path.removeLast();
}
}
LeetCode39.组合总和