1 题目描述
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.
难度:Medium
2 题目样例
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]
]
3 题意分析
有一个正整数集合C和一个正整数目标T。现从C中选出一些数,使其累加和恰好等于T(C中的每个数都只能取一次!!),求所有不同的取数方案。
注意正整数集合中可能存在重复的数字,而这些数字用于组合的时候,会产生重复的排列。题目要求相同的排列只出现一次。
4 思路分析
这个问题和我之前见到的NYOJ上的那道题更像了……依然可以使用深搜来解决。
本题在深搜过程中,需要注意如何避免组合重复,因为不能重复,所以要跳过一样的数字。
代码实现如下
class Solution
{
public:
vector<int> temp;
vector<vector<int> > result;
void DFS(vector<int> &candidates, vector<int> &temp, size_t index, int target)
{
if (target == 0)
{
result.push_back(temp);
return;
}
else
{
int prev = -1;
for (size_t i = index; i < candidates.size(); i++)
{
if (prev == candidates[i])
continue;
if (candidates[i] > target)
return;
prev = candidates[i];
temp.push_back(candidates[i]);
DFS(candidates, temp, i+1, target - candidates[i]);
temp.pop_back();
}
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
{
sort(candidates.begin(), candidates.end());
DFS(candidates, temp, 0, target);
return result;
}
};
我们可以看到,本题的代码和上一题的代码极其的相似,下面就来谈谈是怎么对区别之处进行处理的。(主函数中的去重被删除掉的原因自然是不必说的,毕竟题意都改变了。)
我们可以看到,在DFS函数中我声明了一个初始化为-1(因为集合C中的所有数字都是正数)的变量prev,并在之后进行了如下的操作:
prev = candidates[i];
temp.push_back(candidates[i]);
DFS(candidates, temp, i+1, target - candidates[i]);
temp.pop_back();
由于题意,我们在对数组进行排序后,相同的数字每次只能使用一个,这段代码的作用就是如此:
由于数组中的元素可能有重复,所以我上述代码只需判断上一次循环过程中是否选择到了candidates[i]。如果是则跳过选择下一个candidates元素,直到下标到达比prev大的元素,选择该元素进行下一轮递归(因为数组是按照由小到大的顺序进行排序之后再处理的)。
5 后记
Combination Sum系列问题(后边还有一道III)是很受大家欢迎的问题。通过看题干信息中的like/dislike就能看出大家对于这个系列的问题还是很买账的…
三道题目各有各的特点,我们可以在比较中做一做这三道题,看哪些代码的细微改动可以迎合题目要求,从而获得进步。