2019.2.14
祝大家情人节快乐!O(∩_∩)O哈哈~
题目描述:
Given a set of candidate numbers (candidates
) (without duplicates) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sums to target
.
The same repeated number may be chosen from candidates
unlimited number of times.
Note:
- All numbers (including
target
) will be positive integers. - The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
Example 2:
Input: candidates = [2,3,5], target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
这题给出一个数组,和一个target,要求求出数组中数字之和等于target的数字,返回结果数组。并且数组中的数可以重复使用。
解法一:
回溯算法,也即DFS遍历,这样就可以把所有可能的情况都返回了。我们用index记录当前遍历到的数组的下标,out记录当前的一个解,res返回所有的解即可。
C++代码:
class Solution {
public:
vector<vector<int>> combinationSum(vector<int> &candidates, int target) {
vector<vector<int>> res;
combinationSumDFS(candidates,target,0,{},res);
return res;
}
void combinationSumDFS(vector<int> &candidates, int target, int index, vector<int> out, vector<vector<int>> &res){
if(target<0) return ;
if(target==0) {
res.push_back(out);
return;
}
for(int i=index;i<candidates.size();i++){
out.push_back(candidates[i]);
combinationSumDFS(candidates,target-candidates[i],i,out,res);
out.pop_back();
}
}
};
解法二:
解法一就是最常规的回溯算法,其实我们思考一下,完全可以进行一定的剪枝操作,比如说如果有一个数已经大于target,那么显然不需要考虑这个数了,所以我们先对原数组进行排序,这样一旦遍历到某个数大于target,之后的直接剪掉,或者target已经等于0了,后面的操作也可以剪掉,由此来进行算法的优化。
C++代码:
class Solution {
public:
vector<vector<int>> combinationSum(vector<int> &candidates, int target) {
vector<vector<int>> res;
sort(candidates.begin(), candidates.end());
for (int i = 0; i < candidates.size(); ++i) {
if (candidates[i] > target) break;
else if (candidates[i] == target) {res.push_back({candidates[i]}); continue;}
vector<int> vec = vector<int>(candidates.begin() + i, candidates.end());
vector<vector<int>> tmp = combinationSum(vec, target - candidates[i]);
for (auto a : tmp) {
a.insert(a.begin(), candidates[i]);
res.push_back(a);
}
}
return res;
}
};