# LC 39. Combination Sum ### [Problem link](https://leetcode.com/problems/combination-sum/) ###### tags: `leedcode` `medium` `c++` `Backtracking` Given an array of **distinct** integers <code>candidates</code> and a target integer <code>target</code>, return a list of all **unique combinations** of <code>candidates</code> where the chosen numbers sum to <code>target</code>. You may return the combinations in **any order** . The **same** number may be chosen from <code>candidates</code> an **unlimited number of times** . Two combinations are unique if the **frequency** of at least one of the chosen numbers is different. The test cases are generated such that the number of unique combinations that sum up to <code>target</code> is less than <code>150</code> combinations for the given input. **Example 1:** ``` Input: candidates = [2,3,6,7], target = 7 Output: [[2,2,3],[7]] Explanation: 2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times. 7 is a candidate, and 7 = 7. These are the only two combinations. ``` **Example 2:** ``` Input: candidates = [2,3,5], target = 8 Output: [[2,2,2,2],[2,3,3],[3,5]] ``` **Example 3:** ``` Input: candidates = [2], target = 1 Output: [] ``` **Constraints:** - <code>1 <= candidates.length <= 30</code> - <code>2 <= candidates[i] <= 40</code> - All elements of <code>candidates</code> are **distinct** . - <code>1 <= target <= 40</code> ## Solution 1 #### C++ ```cpp= class Solution { public: vector<vector<int>> res; void backtracking(vector<int> &candidates, int target, vector<int> &path, int &pathSum, int startIdx) { if (pathSum >= target) { if (pathSum == target) { res.push_back(path); } return; } for (int i = startIdx; i < candidates.size(); i++) { path.push_back(candidates[i]); pathSum += candidates[i]; backtracking(candidates, target, path, pathSum, i); path.pop_back(); pathSum -= candidates[i]; } } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { vector<int> path; int pathSum = 0; backtracking(candidates, target, path, pathSum, 0); return res; } }; ``` 剪枝後 ```cpp= class Solution { public: vector<vector<int>> res; void backtracking(vector<int> &candidates, int target, vector<int> &path, int &pathSum, int startIdx) { if (pathSum >= target) { if (pathSum == target) { res.push_back(path); } return; } for (int i = startIdx; i < candidates.size() && pathSum + candidates[i] <= target; i++) { path.push_back(candidates[i]); pathSum += candidates[i]; backtracking(candidates, target, path, pathSum, i); path.pop_back(); pathSum -= candidates[i]; } } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { vector<int> path; int pathSum = 0; sort(candidates.begin(), candidates.end()); backtracking(candidates, target, path, pathSum, 0); return res; } }; ``` >### Complexity >n = candidates.length >| | Time Complexity | Space Complexity | >| ----------- | --------------- | ---------------- | >| Solution 1 | O(n * 2^n) | O(n * 2^n) | ## Note 剪枝多了 ```cpp= sort(candidates.begin(), candidates.end()); 及 for (int i = startIdx; i < candidates.size() && pathSum + candidates[i] <= target; i++) ``` 因為如果目前的合大於target就沒必要進入下層循環了, 如果要這樣判斷就要先用sort排序