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.
- 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] ]
题目的意思是,给出一个目标数target(T),在candidates数组(C)中找到和为T的所有可能的组合,需要注意的一点是,数组中的数字可以重复选择。
这道题可以用回溯的方法解决,若从后往前进行遍历,对于数组中的每个数candidates[i],有如下三种情况:
① candidates[i] < target。则将candidates[i]选入com中,然后递归调用backtrack1函数,注意此时target要减去candidates[i],形成一个与原问题类似的子问题,即从candidates[0]到candidates[i]中找到和为target - candidates[i]的所有可能的组合。
② candidates[i] = target。说明找到一个可能的组合,将com选入res中。
③ candidates[i] > target。这种情况就不必继续探讨了,直接continue。
当然也可以从前往后遍历(backtrack2函数),只需在backtrack1函数的基础上稍微修改即可,因此这两个函数实质上并没有什么区别,对同一个样例来说,运行过程中两个函数被调用的次数一模一样。但有趣的是,用两种函数去提交,得到的Run time相差还是挺大的,backtrack1用了29ms,而backtrack2用了42ms,不清楚为什么两个时间复杂度一样的函数的Run time相差这么大。
至于算法的时间复杂度,跟样例有很大的关系,难以计算。
代码如下:
class Solution {
public:
void backtrack1(vector<int> com, int right, int target) {
for (int i = right; i >= 0; i--) {
if (candidates[i] > target) continue;
else if (candidates[i] == target) {
vector<int> tmp = com;
tmp.push_back(candidates[i]);
res.push_back(tmp);
}
else {
vector<int> tmp = com;
tmp.push_back(candidates[i]);
backtrack1(tmp, i, target - candidates[i]);
}
}
}
void backtrack2(vector<int> com, int left, int target) {
for (int i = left; i < candidates.size(); i++) {
if (candidates[i] > target) break;
else if (candidates[i] == target) {
vector<int> tmp = com;
tmp.push_back(candidates[i]);
res.push_back(tmp);
}
else {
vector<int> tmp = com;
tmp.push_back(candidates[i]);
backtrack2(tmp, i, target - candidates[i]);
}
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
this->candidates = candidates;
//backtrack1(vector<int>(0), candidates.size() - 1, target);
backtrack2(vector<int>(0), 0, target);
return res;
}
private:
vector<int> candidates;
vector<vector<int>> res;
};