1. 程式人生 > 實用技巧 >LeetCode 40 組合總數II

LeetCode 40 組合總數II

LeetCode40 組合總數II

題目描述

給定一個數組 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

candidates 中的每個數字在每個組合中只能使用一次

樣例

輸入: candidates =[10,1,2,7,6,1,5], target =8,
所求解集為:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]
輸入: candidates = [2,5,2,1,2], target = 5,
所求解集為:
[
  [1,2,2],
  [5]
]

演算法分析

與上一題的區別:本體是限制了選取的次數

int k = u;
while(k < candidates.length && candidates[u] == candidates[k]) k++;

//所以candidates[u]有 k-u個
int cnt = k - u;

時間複雜度

Java程式碼

class Solution {
    static List<List<Integer>> ans = new ArrayList<List<Integer>>();
    static void dfs(int[] candidates, int target, int u, int sum, List<Integer> t){
        if(sum > target) return;
        if(u == candidates.length){
            if(sum == target) ans.add(new ArrayList<Integer>(t));
            return;
        } 


        int k = u;
        while(k < candidates.length && candidates[u] == candidates[k]) k++;

        //所以candidates[u]有 k-u個
        int cnt = k - u;
        for(int i = 0; i <= cnt && sum + candidates[u] * i <= target; i++){
            //跳到下一個不同的數字
            dfs(candidates, target, k, sum + i * candidates[u], t);
            t.add(candidates[u]);
        }

        for(int i = 0; i <= cnt && sum + candidates[u] * i <= target; i++){
            t.remove(t.size() - 1);
        }
    }

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        ans.clear();
        List<Integer> t = new ArrayList<Integer>();
        dfs(candidates, target, 0, 0, t);
        return ans;
    }
}