LeetCode解题 39:Combination Sum
Problem 39: Combination Sum [Medium]
Given a set of candidate numbers (candidates
) (without duplicates) and a target number (target
), find all unique combinations in candidates where the candidate
numbers sums to target
.
The same repeated number may be chosen from candidates
unlimited number of times.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
Example 2:
Input: candidates = [2,3,5], target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
来源:LeetCode
解题思路
基本思路为回溯算法,采用深度优先,并使用剪枝减少无用搜索。
- 首先将候选数组按升序排序。
- 每一轮循环从候选数组中选择一个数x加入组合,比较
target'
与x的大小,此处target'
代表每一轮中新的目标值,根据比较结果分为三种情况:
a. 如果target' - x = 0
,说明组合中sum = target,将该种组合加入最终结果result列表里,并剪枝。
b. 如果target' - x < 0
,说明组合中sum > target,不能再加入任何数,也不能将x替换为更大的候选数,因此这里直接剪枝。
c. 如果target' - x > 0
,说明组合中sum < target,还可以继续深入搜索,更新target' = target' - x
,进行递归搜索。 - 注意:为了防止重复组合,每次选择的数x不能比已经存在于组合中的数小,因此递归时需要增加搜索范围参数,不能再次访问之前已经搜索完全的下标。
如下图所示,候选数组为[2,3,6,7]
,target为7
,按深度优先策略,每一轮减去一个数观察剩余的目标值,小于或等于0时都要进行剪枝。其中带颜色的节点为叶节点,表示不再递归搜索,橙色的叶节点代表搜索路径上选择的数属于正确的组合。
要点:回溯算法
、剪枝
Solution (Java)
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Arrays.sort(candidates);
int N = candidates.length;
if(N == 0) return result;
List<Integer> comb = new ArrayList<Integer>();
backtracking(candidates, 0, N, target, comb, result);
return result;
}
private void backtracking(int [] candidates, int index, int N, int target, List<Integer> comb, List<List<Integer>> result){
for(int i = index; i < N; i++){
int next_target = target - candidates[i];
if(next_target == 0){
comb.add(candidates[i]);
result.add(comb);
return;
}
else if(next_target < 0){
return;
}
else{
List<Integer> next_comb = new ArrayList<Integer>(comb);
next_comb.add(candidates[i]);
backtracking(candidates, i, N, next_target, next_comb, result);
}
}
}
}
修改过程
- 没有在递归前创造新的列表空间,供后续选择不同的数,导致搜索过程中所有的数都加入了同一个组合。