Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
- All numbers (including target) will be positive integers.
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
- The solution set must not contain duplicate combinations.
For example, given candidate set 10,1,2,7,6,1,5
and target 8
,
A solution set is: [1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]
解题思路:
求序列的排列组合,典型的回溯算法思想。
如果有兴趣查看Combination Sum版本I,请点击链接。
版本一中candidate没有重复,但是可以允许重复使用candidates中的元素;即,对于{1,2,3,4},选择了1,还可以继续在{1,2,3,4}中选择,返回序列不会出现重复结果;
版本二(本题)设置candidate有重复,但是每个candidate只能使用一次;即,对于{1,2,2,3,4},选择了1,只能继续在{2,2,3,4}中选择;
但是,因为candidate中“2”有重复,如果需要选择“2”,只能选择“第一个2”,不能选择“第二个2”;
因为如果target是10,选择第一个2会返回结果{1,2,3,4},但是选择第二个2,也会出现相同序列{1,2,3,4};造成返回队列包含重复结果;
选择“第一个2”后,还能继续从{2,3,4}中挑选下一个数,因此不会漏选;
代码:
1 class Solution { 2 public: 3 vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { 4 vector<vector<int>> lst; 5 vector<int> ans; 6 sort(candidates.begin(), candidates.end()); 7 Backtracking(lst, ans, candidates, 0, target); 8 return lst; 9 } 10 11 void Backtracking(vector<vector<int>> &lst, vector<int> ans, vector<int> candidates, int idx, int left) { 12 for (int i = idx; i < candidates.size(); ++i) { 13 if (i > idx && candidates[i] == candidates[i-1]) 14 continue; 15 int cur_v = left - candidates[i]; 16 if (cur_v == 0) { 17 ans.push_back(candidates[i]); 18 lst.push_back(ans); 19 return; 20 } 21 22 if (cur_v > 0) { 23 ans.push_back(candidates[i]); 24 Backtracking(lst, ans, candidates, i + 1, cur_v); 25 ans.pop_back(); 26 } else { 27 break; 28 } 29 } 30 return; 31 } 32 };