【转载】Combination Sum
Combination Sum
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
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 2,3,6,7
and target 7
,
A solution set is: [7]
[2, 2, 3]
1 /** 整理的提交代码 2 * 处理复杂度为 3 * 主要思路:与Combination Sum不同之处在与每轮每个候选数字只能取一次,所以下次递归时考虑的当前元素的之后的元素 4 * 所以这次在index中存放的下标是当前元素的下一个位置,以便递归时直接跳过上次考察过的元素,避免重复考察。 5 * 但是在记录结果时需要回复记录在index中的下标。 6 * 回溯法http://www.leetcode.com/2010/09/print-all-combinations-of-number-as-sum.html 7 * 提交结果: 8 * (Judge Small) 9 * Run Status: Accepted! 10 * Program Runtime: 4 milli secs (基本在几毫秒) 11 * Progress: 22/22 test cases passed. 12 * (Judge Large) 13 * Run Status: Accepted! 14 * Program Runtime: 144 milli secs (基本稳定在一百四十几毫秒左右) 15 * Progress: 172/172 test cases passed. 16 */ 17 #include <vector> 18 #include <algorithm> 19 #include <functional> 20 #include <iostream> 21 using namespace std; 22 23 class Solution { 24 private: 25 const int index_count; 26 vector<vector<int> > results; 27 public: 28 Solution() : index_count(10000) {}; 29 // index记录当前找到的候选数字,n表示当前正在找第几个,n是index的下标不是candidates的下标 30 void backtrace(int target, int sum, vector<int> &candidates, int index[], int n) 31 { 32 if (sum > target) 33 { 34 return; // 回溯 35 } 36 if (sum == target) 37 { 38 vector<int> result; 39 for (int i = 1; i <= n; ++i) 40 { 41 result.push_back(candidates[index[i]-1]); // 这里需要减一,因为下面每次记录索引时加了1 42 } 43 results.push_back(result); 44 return; // 此处可以不加,如果不加return由于都是正整数,到下面的计算时会多进行一次无用的递归。 45 } 46 47 // 深度搜索,为了避免重复,每次从当前候选项索引到结尾,上面的i=index[n]可以看出 48 for (int i = index[n]; i < candidates.size(); ++i) 49 { 50 index[n+1] = i+1; // 记录当前考察的候选项索引并加一,下次考察是跳过上次考察过的元素,每轮每个元素值考察一次 51 backtrace(target, sum+candidates[i], candidates, index, n+1); 52 } 53 } 54 vector<vector<int> > combinationSum2(vector<int> &candidates, int target) { 55 // Start typing your C/C++ solution below 56 // DO NOT write int main() function 57 sort(candidates.begin(), candidates.end()); 58 59 int *index = new int[index_count]; 60 memset(index, 0, sizeof(int)*index_count); 61 62 results.clear(); // 提交到leetcode的测试系统上必须添加,它应该是使用一个对象测试所有测试用例。 63 backtrace(target, 0, candidates, index, 0); 64 65 delete[] index; 66 67 // 去重 68 vector<vector<int> >::iterator end = results.end(); 69 sort(results.begin(), end, less<vector<int> >()); 70 vector<vector<int> >::iterator new_end = unique(results.begin(), results.end()); 71 results.erase(new_end, end); 72 73 return results; 74 } 75 }; 76 77 int main() 78 { 79 vector<int> candidates; 80 int number; 81 cout << "input candidates: "; 82 while (cin >> number) 83 { 84 candidates.push_back(number); 85 } 86 87 // 清除缓冲区 88 cin.sync(); 89 cin.clear(); 90 91 int target; 92 cout << "input target: "; 93 cin >> target; 94 95 vector<vector<int> > result; 96 Solution s; 97 result = s.combinationSum2(candidates, target); 98 99 for (size_t i = 0; i < result.size(); ++i) 100 { 101 for (size_t j = 0; j < result[i].size(); ++j) 102 { 103 cout << result[i][j] << ' '; 104 } 105 cout << endl; 106 } 107 cout << endl; 108 109 return 0; 110 }