LeetCode39. 组合总和

☆☆☆代码: 排序剪枝后效率更高 ~

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();

        Arrays.sort(candidates);
        dfs(candidates,0, target, new ArrayList<>(), res);

//        Arrays.sort(candidates);
//        dfs1(candidates, 0, target, new ArrayList<>(), res);
        return res;
    }
    // 难点是如何去除重复的组合
    //(每次i从0开始搜索)      去重前 : [ [2,2,2,2],[2,3,3],[3,2,3],[3,3,2],[3,5],[5,3] ]
    //(每次 i 从index开始搜索)去重后 : [ [2,2,2,2],[2,3,3],[3,5] ]
    // 优化前: 4ms
    // 优化后(排序+剪枝):2ms
    private void dfs(int[] nums,int start, int target, List<Integer> list, List<List<Integer>> res) {
//        if (target < 0) return; // 排序剪枝后不需要加,因为小于0的部分被剪枝
        if (target == 0) {
            res.add(new ArrayList<>(list));
            return;
        }
        for (int i = start; i < nums.length; i++) {
            if (target < nums[i]) break; // 排序后剪枝,后面全是大于target的,直接跳出
            list.add(nums[i]);
            // 由于每一个元素可以重复使用,下一轮搜索的起点依然是 i
            dfs(nums, i,target - nums[i], list, res);
            list.remove(list.size() - 1);
        }
    }
    /**
     * 回溯写法2:做选择
     *      优化前:4ms
     *      优化(排序+剪枝):2ms
     */
    private void dfs1(int[] nums, int index, int target, List<Integer> list, List<List<Integer>> res) {
        if (index == nums.length) return;
        if (target == 0) {
            res.add(new ArrayList<>(list));
            return;
        }
//        if (target < 0) return; // 优化前剪枝
        if (target < nums[index]) return; //优化后剪枝 candidates排序后,target小于当前的值就不用往后算了

        list.add(nums[index]);
        dfs1(nums, index, target - nums[index], list, res);
        list.remove(list.size() - 1);
        dfs1(nums, index + 1, target, list, res);
    }
}
原文地址:https://www.cnblogs.com/HuangYJ/p/14199080.html