【LeetCode】39. 组合总和:背包客解法、dfs解法

【LeetCode】39. 组合总和:背包客解法、dfs解法_第1张图片
【LeetCode】39. 组合总和:背包客解法、dfs解法_第2张图片

我直观的思路是背包客问题。这是一道变种的完全背包客问题,完全背包客问题是,用一定容量的背包去装每种数量不限的具有特定价值和特定重量的金块。

但是速度上很慢。看网友的解法,换用dfs,深度优先遍历的方法,配合剪枝操作。
【LeetCode】39. 组合总和:背包客解法、dfs解法_第3张图片

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        // 无限背包问题。
        List<List<Integer>>[] res = new List[target + 1];// 存储结果
        for (int i = 0; i < target + 1; i++) {
            res[i] = new LinkedList<>();
        }
        // 遍历这些金子。
        for (int i = 0; i < candidates.length; i++) {
            int value = candidates[i];// 第i个金子的重量。
            if (value > target) {
                continue;
            }
            // value <= target  从value开始进行遍历。
            LinkedList<Integer> tmp = new LinkedList<Integer>();
            tmp.add(value);
            res[value].add(tmp);
            for (int j = value + 1; j <= target; j++) {
                if (res[j - value].size() != 0) {
                    List<List<Integer>> ago = res[j - value];
                    for (List<Integer> integers : ago) {
                        LinkedList<Integer> add = new LinkedList<>(integers);
                        add.add(value);
                        res[j].add(add);
                    }
                }
            }

        }
        return res[target];
    }
}

深度优先遍历,配合剪枝操作。速度有所提升。

【LeetCode】39. 组合总和:背包客解法、dfs解法_第4张图片

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> res = new LinkedList<>();
        int begin = 0;
        int len = candidates.length;
        LinkedList<Integer> path = new LinkedList<>();
        dfs(candidates, target, begin, len, res, path);
        return res;
    }

    private void dfs(int[] candidates,
                     int target,
                     int begin,
                     int len,
                     List<List<Integer>> res,
                     LinkedList<Integer> path) {
        if (target == 0) {
            res.add(new LinkedList<>(path));
            return;
        }

        for (int i = begin; i < len; i++) {
            if (candidates[i] > target) {
                return;
            }
            path.add(candidates[i]);
            dfs(candidates, target - candidates[i], i, len, res, path);
            path.removeLast();
        }
    }


}

但是不配合剪枝操作,发现速度又提升了,这个现象的原因可能是不需要将数组进行排序造成的。

【LeetCode】39. 组合总和:背包客解法、dfs解法_第5张图片

public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        //Arrays.sort(candidates);
        List<List<Integer>> res = new LinkedList<>();
        int begin = 0;
        int len = candidates.length;
        LinkedList<Integer> path = new LinkedList<>();
        dfs(candidates, target, begin, len, res, path);
        return res;
    }

    private void dfs(int[] candidates,
                     int target,
                     int begin,
                     int len,
                     List<List<Integer>> res,
                     LinkedList<Integer> path) {
        if (target < 0) return;
        if (target == 0) {
            res.add(new LinkedList<>(path));
            return;
        }

        for (int i = begin; i < len; i++) {
//            if (candidates[i] > target) {
//                return;
//            }
            path.add(candidates[i]);
            dfs(candidates, target - candidates[i], i, len, res, path);
            path.removeLast();
        }
    }


}

你可能感兴趣的:(算法)