###### 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();
}
}
};
```