Combination Sum II

medium array backtracking

Problem

Given a collection of candidate numbers (with duplicates) and a target, find all unique combinations where the candidates sum to target. Each number may be used at most once.

Inputcandidates = [10, 1, 2, 7, 6, 1, 5], target = 8
Output[[1,1,6],[1,2,5],[1,7],[2,6]]
Sort first, then DFS; skip nums[i] when it equals nums[i-1] at the same level.

def combination_sum2(candidates, target):
    candidates.sort()
    out, cur = [], []
    def dfs(start, remain):
        if remain == 0:
            out.append(cur[:]); return
        for i in range(start, len(candidates)):
            if i > start and candidates[i] == candidates[i - 1]: continue
            if candidates[i] > remain: break
            cur.append(candidates[i])
            dfs(i + 1, remain - candidates[i])
            cur.pop()
    dfs(0, target)
    return out
function combinationSum2(candidates, target) {
  candidates.sort((a, b) => a - b);
  const out = [], cur = [];
  function dfs(start, remain) {
    if (remain === 0) { out.push(cur.slice()); return; }
    for (let i = start; i < candidates.length; i++) {
      if (i > start && candidates[i] === candidates[i - 1]) continue;
      if (candidates[i] > remain) break;
      cur.push(candidates[i]);
      dfs(i + 1, remain - candidates[i]);
      cur.pop();
    }
  }
  dfs(0, target);
  return out;
}
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> out = new ArrayList<>();
        dfs(candidates, 0, target, new ArrayList<>(), out);
        return out;
    }
    private void dfs(int[] c, int start, int remain, List<Integer> cur, List<List<Integer>> out) {
        if (remain == 0) { out.add(new ArrayList<>(cur)); return; }
        for (int i = start; i < c.length; i++) {
            if (i > start && c[i] == c[i - 1]) continue;
            if (c[i] > remain) break;
            cur.add(c[i]);
            dfs(c, i + 1, remain - c[i], cur, out);
            cur.remove(cur.size() - 1);
        }
    }
}
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& c, int target) {
        sort(c.begin(), c.end());
        vector<vector<int>> out;
        vector<int> cur;
        dfs(c, 0, target, cur, out);
        return out;
    }
    void dfs(vector<int>& c, int start, int remain, vector<int>& cur, vector<vector<int>>& out) {
        if (remain == 0) { out.push_back(cur); return; }
        for (int i = start; i < (int)c.size(); i++) {
            if (i > start && c[i] == c[i - 1]) continue;
            if (c[i] > remain) break;
            cur.push_back(c[i]);
            dfs(c, i + 1, remain - c[i], cur, out);
            cur.pop_back();
        }
    }
};
Time: O(2ⁿ) Space: O(n)