【每日算法】LeetCode 40 —— 组合总和 II (一百三十二)

题目内容

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

说明:

所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。

示例

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]

题解

本题与上一题唯一的不同点在于,本题的每个元素的个数均有限制,不能无限次枚举给定数组中的元素。

首先,要求出每个元素一共可用多少次,由于给出的candidates不是有序的,我们可以进行排序,将其变为有序,这样,我们能够得出相同元素的个数,在上题求解的思路基础上加上个数的限制就可以得出本题的代码。

具体请看代码注释。

代码

class Solution {
public:
vector<vector<int>> res;
vector<int> path;

vector<vector<int>> combinationSum2(vector<int>& cs, int target) {
sort(cs.begin(),cs.end());//排了序之后,相同元素排列在一起,这样就能够知道每个数能选几次。
dfs(cs,0,target);
return res;
}

void dfs(vector<int>& cs, int u, int target){
if(target == 0){
//说明找到了方案,把答案加入到答案数组中,返回
res.push_back(path);
return;
}
//没找到,直接返回
if(u == cs.size()) return;

int k = u + 1;
while(k < cs.size() && cs[k] == cs[u]) k++;
int cnt = k - u;//求出当前枚举元素一共能用几个
//在循环的时候,添加可适用的元素个数限制即可。
for(int i = 0; cs[u] * i <= target && i <= cnt; i++){
dfs(cs, k, target - cs[u] * i);
path.push_back(cs[u]);
}

for(int i = 0; cs[u] * i <= target && i <= cnt; i++){
path.pop_back();
}
}
};
Author: Frederic Niu
Link: https://www.fredericniu.cn/2021/05/06/【每日算法】LeetCode-40-——-组合总和-II-(一百三十二)/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
我的公众号