组合总和

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:

输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:

输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
方法:递归
思路:
1,首先对数组进行排序,方便操作并且节省开支;
2,数组[2,3,6,7],target = 7,定义一个存放临时结果的list,每次需要从start元素开始,比如,先将2存入list,然后target就变成7-2=5,再将2放入list,target就变成5-2=3,再将2放入list,target就是3-2=1,然后再拿start位置元素还是2,但是2比1大,所以不行,那么就将list最后一个元素2去掉,然后将下一个元素也就是3存入list,这时候target变成了0,满足条件,将这个list存入结果集res里面;
3,按照第二步所描述的过程,递归迭代这个数组,将符合条件的元素组合全部拿到即可!

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<Integer> list = new ArrayList<>();//新建堆栈用来判断
        List<List<Integer>> res = new ArrayList<>();//结果集
        if (candidates == null || candidates.length == 0)
            return res;
        combin(candidates, 0, target, list, res);
        return res;
    }
    //对数组元素(已排序)进行逐个判断以及加入结果集
    private void combin(int[] candidates, int start, int target,List<Integer> list, List<List<Integer>> res) {
        //刚好满足则将结果存入结果集
        if (target == 0) {
            res.add(new ArrayList<>(list));
            return;
        }
        for (int i = start; i < candidates.length; i ++) {
            if (candidates[i] <= target) { //判断是否已经大于target
                list.add(candidates[i]);//将第一个元素存入         
                combin(candidates, i, target -candidates[i] , list, res);//继续判断进栈元素
                list.remove(list.size() - 1);//不满足则将最后一个元素移除,进栈新元素判断
            }
        }         
    }
}

注意:对数组先排序,然后可以判断如果当前元素已经超出,那么后续肯定全部超出,不必浪费时间,可以提升效率!

点赞