leetcode–demo39组合总和
对于这类题我们首先要明确考的是什么算法,不用说就是知道是dfs+回溯,既然是考dfs那么我们就要先画树形图,然后再编码。
因为小编画图不好看,就直接用LeetCode上的图了。
我们接着就要确定递归的终止条件,以及如何进行剪枝。当然你也可以偷懒不剪枝,最后对结果列表进行除重。
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] candidates={2,3,6,7};
System.out.println(new Solution().combinationSum(candidates,7));
}
}
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
//结果列表用于最后的返回
List<List<Integer>> res=new ArrayList<>();
//子列表用于向结果列表中进行添加
List<Integer> path=new ArrayList<>();
//目前列表的和
int sum=0;
//dfs算法的核心
dfs(res,path,candidates,target,sum);
//以下部分最后看
Set<List<Integer>> set=new HashSet<>();
for (List<Integer> ele:
res) {
//一定要排序
Collections.sort(ele);
set.add(ele);
}
res.clear();
for (List<Integer> ele:
set) {
res.add(ele);
}
return res;
}
private void dfs(List<List<Integer>> res, List<Integer> path, int[] candidates, int target, int sum) {
//第一步:递归的终止条件
if(sum>=target){
if (sum==target){
//如果当前分支的和刚好等于target就将当前分支添加到结果列表中
res.add(new ArrayList<>(path));
}
return;
}
//第二步:用递归的思想遍历自己构建的树
for(int i=0;i<candidates.length;i++){
//将当前结点的元素添加到子列表中
path.add(candidates[i]);
//因为本题元素是可以重复使用的所以我们就不使用used[]数组直接递归
dfs(res,path,candidates,target,sum+candidates[i]);//唯一需要改变的只有sum
//第三步:回溯
path.remove(path.size()-1);//把最后一个元素去掉
}
//到这里基本的dfs+回溯算法就已经结束了,但本题不允许有重复的列表,所以我们要排除重复的子列表
//我们有两种处理方法:一种是剪枝,另一种就是使用set。
}
}
当然最好使用剪枝,因为剪枝能提高算法的效率。我这里为了偷懒用的HashSet.结果不出所料,算法效率低了不少。(小丑竟是我自己!)