---
# System prepended metadata

title: 'LeetCode #40 [Combination Sum II](https://leetcode.com/problems/combination-sum-ii/)'
tags: [DFS, Recursion, LeetCode, Medium]

---

###### tags: `LeetCode` `Medium` `DFS` `Recursion`
# LeetCode #40 [Combination Sum II](https://leetcode.com/problems/combination-sum-ii/)
### (Medium)

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

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

注意：解集不能包含重複的組合。

---
這題與#39的差別在於每個數字只能用一次, 而且輸入中可能有重複的值, 所以需要做的 :
1. 尋找解時要從現在數的下一個位置的數開始找
2. 檢查重複機制, 可以容許組合裡有重複的值, 但不能容許有重複的組合(代表不能有不同位置但相同的值作為組合的開頭)
3. 不檢查重複輸入, 最後一次刪除答案數組中的重複組合理論上正確, 但遇到特別噁心的輸入時會超時

---
```
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<int> tmp;
        vector<vector<int>> ans;
        sort(candidates.begin(), candidates.end());
        dfs(candidates, target, 0, tmp, ans);
        
        //這兩行抵擋不了噁心輸入
        //sort(ans.begin(), ans.end()); 要erase前需要先sort
        //ans.erase(unique(ans.begin(), ans.end()), ans.end());
        
        return ans;
    }
    void dfs(vector<int>& candidates, int target, int pos, vector<int>& tmp, vector<vector<int>>& ans){
        if(target==0){
                ans.push_back(tmp);
                return;
            }
        for(int i=pos;i<candidates.size();i++){
            if(candidates[pos]>target)return;
            if(i&&i>pos&&candidates[i]==candidates[i-1])continue;// <-檢查重複
            tmp.push_back(candidates[i]);
            dfs(candidates, target-candidates[i], i+1, tmp, ans);
            tmp.pop_back();
        }
    }
};
```