39. 组合总和

题目地址: https://leetcode-cn.com/problems/combination-sum/

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

说明:

  • candidates 中的数字可以无限制重复被选取。
  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。 

思路

回溯算法居然有模板可以套用,真的是太好用了。

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return

for 选择 in 选择列表:
    做选择
    backtrack(路径, 选择列表)
    撤销选择

代码

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
       List<List<Integer>> result = new ArrayList();
      //先排序,便于后面剪枝
       Arrays.sort(candidates);

       dfs(candidates, target, 0, new ArrayList(), result);

       return result;
    }

    /**
     * @param nums 原数组
     * @param val 剩余数值
     * @param start 选择区域,起点
     * @param path 选择列表
     * @param result 结果集
     */
    void dfs(int[] nums, int val, int start,  List<Integer> path, List<List<Integer>> result){
        if(val == 0){ //找到
            List<Integer> tmp = new ArrayList(path.size());
            for(Integer i: path){
                tmp.add(i);
            }
            result.add(tmp);
            return;
        }

        for(int i=start;i < nums.length; i++){
            int v = nums[i];
            if(v > val){//前面已经排序了,这里就可以直接跳过
                break;
            }
            //做选择
            path.add(v);
            dfs(nums, val - v, i, path, result);
            //撤销选择
            path.remove(path.size() -1 );
        }

    }
}