【LeetCode】39. 組合總和:揹包客解法、dfs解法

在這裏插入圖片描述
在這裏插入圖片描述

我直觀的思路是揹包客問題。這是一道變種的完全揹包客問題,完全揹包客問題是,用一定容量的揹包去裝每種數量不限的具有特定價值和特定重量的金塊。

但是速度上很慢。看網友的解法,換用dfs,深度優先遍歷的方法,配合剪枝操作。
在這裏插入圖片描述

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];
    }
}

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

在這裏插入圖片描述

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();
        }
    }


}

但是不配合剪枝操作,發現速度又提升了,這個現象的原因可能是不需要將數組進行排序造成的。

在這裏插入圖片描述

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();
        }
    }


}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章