不去重的情况图
去重+剪枝的情况:
public class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
int len = candidates.length;
List<List<Integer>> res = new ArrayList<>();
if (len == 0) {
return res;
}
// 排序是剪枝的前提(只是排序也耗时)
Arrays.sort(candidates);
Deque<Integer> path = new ArrayDeque<>();
dfs(candidates, 0, len, target, path, res);
return res;
}
/**
begin:表示开始递归的数组的元素下标开始
target:表示需要达到的组合目标值(如果target>0就需要递归)
path:代表当前的队列情况
*/
private void dfs(int[] candidates, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {
// 由于进入更深层的时候,小于 0 的部分被剪枝,因此递归终止条件值只判断等于 0 的情况
if (target == 0) {
res.add(new ArrayList<>(path));
return;
}
// for循环用于同层的回溯, dfs用于向下的递归
for (int i = begin; i < len; i++) {
// 重点理解这里剪枝,前提是候选数组已经有序,
if (target - candidates[i] < 0) {
break;
}
path.addLast(candidates[i]);
//这里第二层从i开始避免了组合列表的重复情况(在i之前的元素不会再使用)
dfs(candidates, i, len, target - candidates[i], path, res);
//将队列中原先添加的元素撤销 ,用于同层的下一个元素替换
path.removeLast();
}
}
}