1. 程式人生 > >leetcode 39. Combination Sum-回溯演算法|遞迴|非遞迴

leetcode 39. Combination Sum-回溯演算法|遞迴|非遞迴

【思路-Java】 回溯演算法|遞迴實現

本題採用回溯演算法。

1. 基本思路是先排好序,這樣做的目的是為了對陣列後面不可能出現的情況進行排除,有利於減少查詢時間,即剪枝操作

2. 外層迴圈對陣列元素依次進行遍歷,依次將 nums 中的元素加入中間集,一旦滿足條件,就將中間集加入結果集

3. 然後每次遞迴中把剩下的元素一一加到結果集合中,並且把目標減去加入的元素,然後把剩下元素(包括當前加入的元素)放到下一層遞迴中解決子問題。

演算法複雜度因為是NP問題,所以自然是指數量級的:

public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();
        dfs(res, temp, target, candidates, 0);
        return res;
    }
    private void dfs(List<List<Integer>> res, List<Integer> temp, int target,
        int[] candidates, int j) {
        if(target == 0) {  //滿足條件,將中間集加入結果集
            res.add(new ArrayList<>(temp));
        }
        for(int i = j; i < candidates.length && target >= candidates[i]; i++) {  //target>=candidates[i]是剪枝操作
            temp.add(candidates[i]);
            dfs(res, temp, target - candidates[i], candidates, i);
            temp.remove(temp.size() - 1);
        }
    }
}
168 / 168 test cases passed. Runtime: 5 ms  Your runtime beats 76.66% of javasubmissions.

【思路2-Python】回溯演算法|非遞迴實現

提供非遞迴實現程式碼
class Solution(object):
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        candidates, res, stack, lenth=sorted(set(candidates)), [], [(0, [], target)], len(candidates)
        while stack:
            i, temp, tar=stack.pop()
            while i<lenth and tar>0:
                if candidates[i]==tar: res+=temp+[candidates[i]],
                stack+=(i, temp+[candidates[i]], tar-candidates[i]),
                i+=1
        return res
168 / 168 test cases passed. Runtime: 96 ms  Your runtime beats 92.59% of pythonsubmissions.