组合总和
涉及知识:回溯,剪枝
分析:
本题为典型的回溯算法。
在一般的情况下,如果不考虑每一个数字可以重复使用多次的话,那么对于每一个元素便只有两种情况,取或者不取。然后再对不符合条件的情况进行判断,剪枝即可。
在本题中,由于每一个元素可以无限次被使用,因此每一个元素需要被判断多次。
注意:由于题目中规定不可以包含重复的组合,因此不可以取当前元素之前已经取过的元素。
例如:2、3、5、8、9;在取 5 的时候,不可以返回去再取 2 或 3。表达的不是很清楚,就先意会一下吧。
代码:
import java.util.ArrayList;
import java.util.List;
/*
* @lc app=leetcode.cn id=39 lang=java
*
* [39] 组合总和
*/
class Solution {
public List<List<Integer>> resList = new ArrayList<>();
public int target = 0;
public int[] candidates;
public int len = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
this.target = target;
this.candidates = candidates;
this.len = candidates.length;
dfs(new ArrayList<>(), 0, 0);
return resList;
}
/**
* @param list 记录已经取到的元素
* @param level 表示从第几个元素开始
* @param sum 记录当前数组中元素的值的总和
*/
public void dfs(ArrayList<Integer> list, int level, int sum){
//判断是否达到目标值或者已经超过目标值来剪枝
if(sum == target){
resList.add(new ArrayList<>(list));
return;
} else if(sum > target){
return;
}
//从 level 开始便保证了不会取到重复的组合
for(int i = level; i < len; ++i){
list.add(candidates[i]);
dfs(list, i, sum + candidates[i]);
list.remove(list.size() - 1);
}
return;
}
}