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]
这个题是一个NP问题,方法仍然是N-Queens中介绍的套路。基本思路是先排好序,然后每次递归中把剩下的元素一一加到结果集合中,并且把目标减去加入的元素,然后把剩下元素(包括当前加入的元素)放到下一层递归中解决子问题。算法复杂度因为是NP问题,所以自然是指数量级的。代码如下:
- public ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {
- ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
- if(candidates == null || candidates.length==0)
- return res;
- Arrays.sort(candidates);
- helper(candidates,0,target,new ArrayList<Integer>(),res);
- return res;
- }
- private void helper(int[] candidates, int start, int target, ArrayList<Integer> item,
- ArrayList<ArrayList<Integer>> res)
- {
- if(target<0)
- return;
- if(target==0)
- {
- res.add(new ArrayList<Integer>(item));
- return;
- }
- for(int i=start;i<candidates.length;i++)
- {
- if(i>0 && candidates[i]==candidates[i-1])
- continue;
- item.add(candidates[i]);
- helper(candidates,i,target-candidates[i],item,res);
- item.remove(item.size()-1);
- }
- }
注意在实现中for循环中第一步有一个判断,那个是为了去除重复元素产生重复结果的影响,因为在这里每个数可以重复使用,所以重复的元素也就没有作用了,所以应该跳过那层递归。这道题有一个非常类似的题目Combination Sum II,有兴趣的朋友可以看看,一次搞定两个题哈。
class Solution {
private:
void combineHelper(vector<int> &candidates, int start, int sum, int target, vector<int> &answer,
vector<vector<int> > &result) {
if (sum == target) {
result.push_back(answer);
return;
}
if (start == candidates.size() || candidates[start] + sum > target) {
return;
}
answer.push_back(candidates[start]);
combineHelper(candidates, start, sum+candidates[start], target, answer, result);
answer.pop_back();
combineHelper(candidates, start+1, sum, target, answer, result);
}
public:
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
/* https://oj.leetcode.com/problems/combination-sum/
* The same repeated number may be chosen from candidates unlimited number of times.
* 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).
*/
vector<vector<int> > result;
vector<int> answer;
sort(candidates.begin(), candidates.end());
combineHelper(candidates, 0, 0, target, answer, result);
return result;
}
};
//This is just like a coin change/knapsack problem. We need to create a vector of the size of target. //and for each o(1)...o(target) we get the values. and if in between we find any sum == target, //add that into the result
class Solution {
public:
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
vector< vector< vector<int> > > combinations(target + 1, vector<vector<int>>());
combinations[0].push_back(vector<int>());
for (auto& score : candidates)
for (int j = score; j <= target; j++)
if (combinations[j - score].size() > 0) {
auto tmp = combinations[j - score];
for (auto& s : tmp)
s.push_back(score);
combinations[j].insert(combinations[j].end(), tmp.begin(), tmp.end());
}
auto ret = combinations[target];
for (int i = 0; i < ret.size(); i++)
sort(ret[i].begin(), ret[i].end());
return ret;
}
};
class Solution {
public:
vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
sort(candidates.begin(), candidates.end());
vector< vector< vector<int> > > combinations(target + 1, vector<vector<int>>());
combinations[0].push_back(vector<int>());
for (auto& score : candidates)
for (int j = score; j <= target; j++){
auto sls = combinations[j - score];
if (sls.size() > 0) {
for (auto& s : sls)
s.push_back(score);
combinations[j].insert(combinations[j].end(), sls.begin(), sls.end());
}
}
return combinations[target];
}
};
浙公网安备 33010602011771号