给定一个正数数组和target, 求所有组合为target的解。
直观解决方案是蛮力搜索,保存搜索路径,对于无法确定搜索次数的,只能使用递归搜索,准确描述搜索停止条件即可。
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> r = new ArrayList();
combinationSum(candidates, target, new Stack<>(), r);
return r;
}
public void combinationSum(int[] candidates, int target, Stack<Integer> s, List<List<Integer>> x) {
if (target == 0) {
x.add(s.stream().collect(Collectors.toList()));
// System.out.println(s);
}
for(int i=0; i<candidates.length; ++i) {
s.push(candidates[i]);
int[] a = new int[candidates.length-i];
System.arraycopy(candidates, i, a, 0,candidates.length-i);
combinationSum(a, y, s, x);
s.pop();
}
}
}
提前对输入数组排序,搜索过程中可剪枝
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> r = new ArrayList();
combinationSum(candidates, target, new Stack<>(), r);
return r;
}
public void combinationSum(int[] candidates, int target, Stack<Integer> s, List<List<Integer>> x) {
if (target == 0) {
x.add(s.stream().collect(Collectors.toList()));
// System.out.println(s);
}
for(int i=0; i<candidates.length; ++i) {
int y = target-candidates[i]; // 当搜索target小于0时,后续candidates可忽略
if(y<0) break;
s.push(candidates[i]);
int[] a = new int[candidates.length-i];
System.arraycopy(candidates, i, a, 0,candidates.length-i);
combinationSum(a, y, s, x);
s.pop();
}
}
}
若候选集中有重复的元素,为保证结果集中无重复组合,需对已搜索过的元素过滤掉,此外为保证结果集中一个元素只能出现一次,则在搜索候选集中去重当前元素
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> r = new ArrayList();
combinationSum(candidates, target, new Stack<>(), r);
return r;
}
public void combinationSum(int[] candidates, int target, Stack<Integer> s, List<List<Integer>> x) {
if (target == 0) {
x.add(s.stream().collect(Collectors.toList()));
// System.out.println(s);
}
for(int i=0; i<candidates.length; ++i) {
if(i>0 && candidates[i]==candidates[i-1]) continue; //若候选集中有重复的元素skip,保证结果集中无重复组合
int y = target-candidates[i];
if(y<0) break;
s.push(candidates[i]);
int[] a = new int[candidates.length-i-1];
System.arraycopy(candidates, i+1, a, 0,candidates.length-i-1); //候选集中不包含当前元素
combinationSum(a, y, s, x);
s.pop();
}
}
}