这个题目就是很典型的回溯法,说实话,我讲不明白回溯法是个咋回事,但是会写一点(气人不)。这个题目是我写完电话号码组合后紧接着做得题目,可能是手感来了。总之核心思想就是要画一个树,然后在某个时刻要学会剪枝(不符合条件时直接返回)。代码如下:
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new LinkedList<>();
backtrace(candidates, 0, target, result, new ArrayList<Integer>(), 0);
return result;
}
/**
*
* @param candidates 候选数
* @param cur 当前的值总和(temp里面数的总和)
* @param target 目标值
* @param result 存放所有的结果
* @param temp 当前的值的集合
* @param index 当前要访问数字在candidates中的下标
*/
private static void backtrace(int[] candidates, int cur, int target, List<List<Integer>> result,
List<Integer> temp, int index) {
//当前的值等于target,则把当前的集合加入到结果集中
if (cur == target) {
result.add(temp);
return;
}
//当前的值大于target,则直接返回(剪枝)
if (cur > target) {
return;
}
//有了当前的值和当前集合,尝试将当前位置及后面的每一个数加到当前值和当前集合中
//此处一定是要从index开始,否则会出现重复情况,要按顺序加到现有集合中
for (int i = index; i < candidates.length; ++i) {
//此处要新创建一个数组并把temp复制进去
List<Integer> current = new LinkedList<>(temp);
current.add(candidates[i]);
backtrace(candidates, cur + candidates[i], target, result, current, i);
}
}