LeetCode:Combination Sum I II
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]
简单的回溯法(递归实现).
比如对于数组3,2,6,7,target = 7,对数组排序得到[2,3,6,7]
1、第1个数字选取2, 那么接下来就是解决从数组[2,3,6,7]选择数字且target = 7-2 = 5
2、第2个数字选择2,那么接下来就是解决从数组[2,3,6,7]选择数字且target = 5-2 = 3
3、第3个数字选择2,那么接下来就是解决从数组[2,3,6,7]选择数字且target = 3-2 = 1
4、此时target = 1小于数组中的所有数字,失败,回溯,重新选择第3个数字
5、第3个数字选择3,那么接下来就是解决从数组[2,3,6,7]选择数字且target = 3-3 = 0
6、target = 0,找到了一组解,继续回溯寻找其他解
需要注意的是:如果数组中包含重复元素,我们要忽略(因为每个数字可以选择多次,如果不忽略的话,就会产生重复的结果)。貌似oj的测试集数组中都不包含重复的数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class Solution { private : vector<vector< int > > res; public : vector<vector< int > > combinationSum(vector< int > &candidates, int target) { sort(candidates.begin(), candidates.end()); //为了输出结果递增,因此先对数组排序 vector< int > tmpres; helper(candidates, 0, target, tmpres); return res; } //从数组candidates[index,...]寻找和为target的组合 void helper(vector< int > &candidates, const int index, const int target, vector< int >&tmpres) { if (target == 0) { res.push_back(tmpres); return ; } for ( int i = index; i < candidates.size() && target >= candidates[i]; i++) if (i == 0 || candidates[i] != candidates[i-1]) //由于每个数可以选取多次,因此数组中重复的数就不用考虑 { tmpres.push_back(candidates[i]); helper(candidates, i, target - candidates[i], tmpres); tmpres.pop_back(); } } }; |
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.
- 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 10,1,2,7,6,1,5
and target 8
,
A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]
和上一题差不多,只是每个元素只能选一次。
由于有重复元素的存在,比如数组为[1(1),1(2),2,3],target = 6. 可能出现重复结果1(1),2,3 和 1(2),2,3 本文地址
我们可以如下处理:如果数组中当前的数字出现重复,在前面重复了k次,且临时结果数组中也包含了k个当前数字,那么当前的数字可以选择;否则就不选择当前数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Solution { private : vector<vector< int > >res; public : vector<vector< int > > combinationSum2(vector< int > &candidates, int target) { sort(candidates.begin(), candidates.end()); vector< int > tmpres; helper(candidates, 0, target, tmpres, 0); return res; } //从数组candidates[index,...]寻找和为target的组合,times为前一个数字candidates[index-1]重复出现的次数 void helper(vector< int > &candidates, const int index, const int target, vector< int >&tmpres, int times) { if (target == 0) { res.push_back(tmpres); return ; } for ( int i = index; i < candidates.size() && target >= candidates[i]; i++) { if (i > 0 && candidates[i] == candidates[i-1])times++; else times = 1; if (times == 1 || (tmpres.size() >= times-1 && tmpres[tmpres.size()-times+1] == candidates[i])) { tmpres.push_back(candidates[i]); helper(candidates, i+1, target - candidates[i], tmpres, times); tmpres.pop_back(); } } } }; |
还有一种方法是,在每个子问题的数组中,重复的数字都不选择,这种更简洁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class Solution { private : vector<vector< int > >res; public : vector<vector< int > > combinationSum2(vector< int > &candidates, int target) { sort(candidates.begin(), candidates.end()); vector< int > tmpres; helper(candidates, 0, target, tmpres); return res; } //从数组candidates[index,...]寻找和为target的组合 void helper(vector< int > &candidates, const int index, const int target, vector< int >&tmpres) { if (target == 0) { res.push_back(tmpres); return ; } for ( int i = index; i < candidates.size() && target >= candidates[i]; i++) { if (i > index && candidates[i] == candidates[i-1]) continue ; //当前子问题中,重复数字都不选择 tmpres.push_back(candidates[i]); helper(candidates, i+1, target - candidates[i], tmpres); tmpres.pop_back(); } } }; |
【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3802647.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理