###### tags: `LeetCode` `Medium` `DFS`
# LeetCode #39 [Combination Sum](https://leetcode.com/problems/combination-sum/)
### (Medium)
給定一個無重複元素的正整數數組 candidates 和一個正整數 target ,找出 candidates 中所有可以使數字和為目標數 target 的唯一組合。
candidates 中的數字可以無限制重複被選取。如果至少一個所選數字數量不同,則兩種組合是唯一的。
對於給定的輸入,保證和為 target 的唯一組合數少於 150 個。
---
由於搜尋順序為candidate[i]開始往後搜尋, 因此在做第candidate[i+1]的組合時不用往前確認(因為之前的組合已經被前面的元素檢查過了)。
核心概念為
```
tmp.push_back(candidates[i]);
dfs(candidates, target-candidates[i], i, tmp, ans);
tmp.pop_back();
```
先將輪到的元素candidate[i]放進回傳數組中, 然後再度呼叫遞迴函式, 而遞迴函式又會再將candidate[i]放入回傳數組中, 如此反覆直到target=0或是target值小於candidate[i]。此時退出最底層遞迴(如果target=0則須將回傳數組放入答案數組中), 並且pop出回傳數組的最後一個元素(candidate[i]), 然後從candidate[i+1]開始嘗試...直到candidate[n-1]。最後可以得出第一個元素為candidate[i]的所有組合, 然後接續得出第一個元素為candidate[i+1]的所有組合...直到得出所有組合, 迴圈中止。
---
```
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> tmp;
sort(candidates.begin(), candidates.end());
dfs(candidates, target, 0, tmp, ans);
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[i]>target)break;
tmp.push_back(candidates[i]);
dfs(candidates, target-candidates[i], i, tmp, ans);
tmp.pop_back();
}
}
};
```