题目:
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.
- 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]
]
解答:
本题通过动态规划的方法求出输入数组的所有不重复的子集,参见我的这篇文章http://blog.csdn.net/zhaopengnju/article/details/51427484 。在求取子集的过程中跳过和已经大于target的子集并且保存和等于target的子集。
class Solution {
public:
//用动态规划的方法求取candidates的子集
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
std::sort(candidates.begin(), candidates.end());
vector<vector<int>> res;
vector<vector<int>> subsets(1);
vector<int> sum(1, 0);//存储subsets中每个集合的元素和
int prev = -1, prev_index = -1;
for (int i = 0; i < candidates.size(); ++i)
{
int size = subsets.size();
if (prev != candidates[i])
{
prev_index = 0;
}
//如果当前元素跟上一个元素不同,那么在每个已有的集合中添加当前元素构成新的集合
//如果当前元素跟上一个元素相同,那么只向上一个元素更新过的集合中添加当前元素,否则会重复
for (int j = prev_index; j < size; ++j)
{
int new_sum = sum[j] + candidates[i];
if (new_sum < target)
{
subsets.push_back(subsets[j]);//复制第j个集合,并在它里面插入新元素candidates[i]
subsets.back().push_back(candidates[i]);
sum.push_back(new_sum);
}
else if (new_sum == target) //满足要求,压入result中
{
res.push_back(subsets[j]);
res.back().push_back(candidates[i]);
}
}
prev_index = size;//指向该轮新加入的第一个集合
prev = candidates[i];//指向上一个元素
}
return res;
}
};