Leetcode39. 组合总和

210 阅读1分钟

要求:

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

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

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

示例:

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

思路:

  • 递归加回溯剪枝
  1. 先创建一个全局变量List<List<Integer>>用来最后将其返回。
  2. 对特殊情况进行判断,什么时候直接返回
  3. 创建新的辅助记录的List<Integer>
  4. 递归
  5. 返回结果 递归:
  6. 先写递归终止条件:target<0就直接返回;target==0就添加元素进辅助列表
  7. 正常情况下就进入循环:
    1. 先把元素这一轮的元素添加进去
    2. 是从前往后加的,target做减法,每个数字都可以用s无数次,所以递归可以从当前元素开始
    3. 循环的最后需要剪枝,就是把每次最新添加的数删除,不然会导致数字一直累加。

代码:

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);//对数组进行排序,防止出现重复时无法有效剪枝
        List<Integer> list = new ArrayList<>();
        if (candidates.length == 0 || candidates == null || candidates[0] > target) return res;
        dfs(0, candidates, target, list);
        return res;
    }
    public void dfs(int i, int[] nums, int sum, List<Integer> list) {//起始索引,数组,和,辅助列表
        if(sum < 0) return;
        if(sum == 0) res.add(new ArrayList<>(list));
        else {
            for(int j = i; j < nums.length; j++) {
                list.add(nums[j]);
                dfs(j, nums, sum-nums[j], list);
                list.remove(list.size()-1);
            }
        }
    }
}