算法小白,最近刷LeetCode。希望能够结合自己的思考和别人优秀的代码,对题目和解法进行更加清晰详细的解释,供大家参考^_^
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]
]
与39题不同的是,该题目的候选集中有重复数字,如果按照39题的方式,结果集中也会出现重复方案,因此,需要在递归的同时进行去重。
另一方面,题目要求每个元素最多只能使用1次,当某个元素连续出现m次时,相当于该元素可以使用0-m次,这样一来,就相当于做了去重的工作,同时还将题目变成了和39题几乎一样的方式。
class Solution {
public:
// candi是元素集合,tar是当前目标和值,idx是当前使用元素的索引
// vi为方案序列,res为方案结果集
void fun(vector<int> &candi, int tar, int idx, vector<int> vi, vector<vector<int>> &res) {
if (tar == 0) { res.push_back(vi); return ; }
if (idx == candi.size()) return ;
if (tar < candi[idx]) return ;
int len = 1;
while(idx+1 < candi.size() && candi[idx] == candi[idx+1]) {++idx; ++len; } // 计算重复元素个数
for (int i = 0; i <= len; ++i){
vector<int> vi_t(vi);
int ii = i;
while (ii--) {
vi_t.push_back(candi[idx]);
}
fun(candi, tar-candi[idx]*i, idx+1, vi_t, res); // 递归
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<vector<int>> res;
fun(candidates, target, 0, vector<int>{}, res);
return res;
}
};