题目要求:
分析:
这是一道深度优先遍历算法题目,并且为了避免重复的解,还涉及到剪枝算法。
总体思想我参考了标准答案,网址为:添加链接描述
我把他的图拿过来,这道题目就很清晰明了了,如下所示:
这个图真的是不要画得太好。剪枝算法就是为了去掉途中绿色框框框起来的部分(它们是重复的),要实现剪枝,首先就得对这个数组中的数字进行排序,使用Arrays.sort()方法即可。
看到这种类似于树的结构,我们条件反射就要想到利用递归。没有递归完的时候,它们剩下的值都是大于0的,而递归完之后,会出现图上所示的两种情况:
- 最终结果为负数:这就表明这个结果不是我们想要的,于是我们要把它给丢掉;
- 最终结果为0:这个结果是我们想要的,我们把它给存到我们的集合里面去。
在这里,我们需要两个集合:
一个集合拿来存放加起来可能为target的组合,我们将其命名为result,如果组合里加起来不是target,就直接丢掉,如果它加起来是target,那么就要把它给存到我们的大集合里,我们把这个大集合命名为resultList。
还有需要注意的一点是,当我们遍历完之后,我们需要将result中最后的值给去掉。
具体代码如下:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> resultList = new ArrayList<>();
List<Integer> result = new ArrayList<>();
Arrays.sort(candidates);
compare(candidates, target, 0, result, resultList);
return resultList;
}
private void compare(int[] candidates, int target, int start, List<Integer> result, List<List<Integer>> resultList) {
if(target < 0) {
return;
} else if(target == 0) {
resultList.add(new ArrayList<>(result));
} else {
for(int i = start; i < candidates.length; i++) {
result.add(candidates[i]);
compare(candidates, target - candidates[i], i, result, resultList);
//回溯
result.remove(result.size() - 1);
}
}
}
}
Tips:在代码中,将result add进resultList集合中时,我们使用的时resultList.add(new ArrayList<>(result)),而不是直接resultList.add(result),这是因为因为result是一个对象的引用,result会因为remove方法而变化,会影响到resultList.