39-组合总和(回溯法)

 

思路:

思路:根据示例 1:输入: candidates = [2,3,6,7],target = 7。

候选数组里有 2 ,如果找到了 7 - 2 = 5 的所有组合,再在之前加上 2 ,就是 7 的所有组合;
同理考虑 3,如果找到了 7 - 3 = 4 的所有组合,再在之前加上 3 ,就是 7 的所有组合,依次这样找下去;
上面的思路就可以画成下面的树形图。

 

 

 

 

 

去重复
在搜索的时候,需要设置搜索起点的下标 begin ,由于一个数可以使用多次,下一层的结点从这个搜索起点开始搜索;
在搜索起点 begin 之前的数因为以前的分支搜索过了,所以一定会产生重复。

剪枝提速
如果一个数位搜索起点都不能搜索到结果,那么比它还大的数肯定搜索不到结果,基于这个想法,我们可以对输入数组进行排序,以减少搜索的分支;

排序是为了提高搜索速度,非必要;

 

搜索问题一般复杂度较高,能剪枝就尽量需要剪枝。把候选数组排个序,遇到一个较大的数,如果以这个数为起点都搜索不到结果,后面的数就更搜索不到结果了。

class Solution {//回溯法
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res =new ArrayList<>();
        Arrays.sort(candidates);
        backpack(res,candidates,target,0,new ArrayList<Integer>());
        return res;
    }
    public void backpack(List<List<Integer>> res,int [] candidates,int target,int i,List<Integer> tmp)//i是搜索起点的下标,因为数字可以重复选取,下一层的结点从这个搜索起点开始搜索;这个起点之前的一定被搜索过了,所以不需要
    {
        if(target==0)
        {
            res.add(new ArrayList<>(tmp));
            return;
        }
        if(target<0) return;
        for(int start=i;start<candidates.length;start++)//一轮循环,找的是tmp里加入了candidates[start]的所有组合。下一轮,找的是,tmp里加入candidates[start+1](candidates[start]不加,因为带这个数的所有组合都找到了)的所有组合。
        {
           // if(target<0)break;
            tmp.add(candidates[start]);
            backpack(res,candidates,target-candidates[start],start,tmp);
            tmp.remove(tmp.size()-1);
        }
    }
}

  

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

posted @ 2020-04-23 16:21  弓呆的胖次  阅读(183)  评论(0编辑  收藏  举报