# Combination Sum II

Given a collection of candidate numbers (`candidates`) and a target number (`target`), find all unique combinations in`candidates` where the candidate numbers sums to`target`.

Each number in`candidates` may only be used **once** in the combination.

**Note:**

* All numbers (including`target`) will be positive integers.
* The solution set must not contain duplicate combinations.

**Example 1:**

```
Input:
 candidates = 
[10,1,2,7,6,1,5]
, target = 
8
,

A solution set is:

[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]
```

**Example 2:**

```
Input:
 candidates = [2,5,2,1,2], target = 5,

A solution set is:

[
  [1,2,2],
  [5]
]
```

## Analysis

Basically the same as Combination Sum, yet need to handle

1\) duplicated elements

2\) each element may only use once

## Solution

Backtracking

基本和Combination Sum一样，但是（1）要处理重复元素的问题，并且（2）每个元素只能用一次

因此两点改变：

传入startIdx时，用i + 1，而不是i；

在每次循环结束后，如果有重复，则i++，跳过剩余的重复部分

```java
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();

        Arrays.sort(candidates);
        comboHelper(target, 0, 0, candidates, new ArrayList<Integer>(), ans);

        return ans;
    }

    private void comboHelper(int target, int sum, int startIdx, int[] candidates, 
                            List<Integer> combo, List<List<Integer>> ans) {
        if (sum == target) {
            ans.add(new ArrayList<Integer>(combo));
            return;
        }

        if (sum > target) {
            return;
        }

        for (int i = startIdx; i < candidates.length; i++) {
            combo.add(candidates[i]);
            comboHelper(target, sum + candidates[i], i + 1, candidates, combo, ans);
            combo.remove(combo.size() - 1);
            while (i < candidates.length - 1 && candidates[i + 1] == candidates[i]) {
                i++;
            }
        }
    }
}
```

用remain而不是target，sum减少参数个数

```java
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();

        Arrays.sort(candidates);
        comboHelper(target, 0, candidates, new ArrayList<Integer>(), ans);

        return ans;
    }

    private void comboHelper(int remain, int startIdx, int[] candidates, 
                            List<Integer> combo, List<List<Integer>> ans) {
        if (remain == 0) {
            ans.add(new ArrayList<Integer>(combo));
            return;
        }

        if (remain < 0) {
            return;
        }

        for (int i = startIdx; i < candidates.length; i++) {
            combo.add(candidates[i]);
            comboHelper(remain - candidates[i], i + 1, candidates, combo, ans);
            combo.remove(combo.size() - 1);
            while (i < candidates.length - 1 && candidates[i + 1] == candidates[i]) {
                i++;
            }
        }
    }
}
```
