LeetCode/solutions/40. Combination Sum II.md
2019-01-07 20:05:41 +08:00

58 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [40. Combination Sum II](https://leetcode.com/problems/combination-sum-ii/)
# 思路
题意从一个数组candidates允许存在重复元素里面选一些数字出来使这些数字的和恰好为targetcandidates里的数只能使用一次。可见这题与[39. Combination Sum](https://leetcode.com/problems/combination-sum/)有两个不同点:
1. 在挑选数字出来时candidates里的数只能使用一次
2. candidates里的元素允许重复
上面两个不同点也对应于代码中两个不同点(见下面的代码)。
思路其实和39题类似的建议先去看看我写的[39题题解](https://github.com/ShusenTang/LeetCode/blob/master/solutions/39.%20Combination%20Sum.md)。
仍然是一个回溯题类似DFS为了避免得到重复结果先对数组进行排序常规操作
为了进行递归调用我们定义了一个函数helper传入的参数有
* nums - 当前被选中的数
* candidates - 就是题意里面的数组(从小到大排序好的)
* start - 只能考虑数组candidates下标为start及后面的数
* curr_target - 当前的目标我们希望的就是nums的元素和加上curr_target就等于target
helper函数定义如下
* 当`curr_target == 0`时说明nums的元素和就等于targetnums就是一组我们要求的数push进结果数组即可。
* 当`start >= candidates.size()`时说明start已经超过了candidates最大下标返回即可
* 当`candidates[start] > curr_target`时说明candidates中当前可用的最小的数都比curr_target大也是直接返回。
--------------上面都和39题一样的只是下面有两个不同点---------------
* 前面三个条件都不满足时,假设`k = candidates[start]`就有两条路要走:
1. 将k加入到nums中令`curr_target = curr_target - k`且`start = start+1`, 进入下一层递归;
2. 不将k加入到nums中, 由于candidates里的元素允许重复所以candidates[start+1]也就可能等于k所以我们应该让start移动到最后一个k所在位置再令`start + 1`进入下一层递归;
# C++
``` C++
class Solution {
private:
vector<vector<int>>res;
void helper(vector<int>& nums, const vector<int>& candidates, int start, const int& curr_target){
if(curr_target == 0){
res.push_back(nums);
return;
}
if(start >= candidates.size() || candidates[start] > curr_target) return;
nums.push_back(candidates[start]);
helper(nums, candidates, start + 1, curr_target - candidates[start]); // 不同点一39传入的是start因为39允许多次使用candidates里的数
nums.pop_back();
// 不同点二因为candidates里的元素允许重复所以要跳过这些重复元素
while(start < candidates.size() - 1 && candidates[start] == candidates[start+1])
start++;
helper(nums, candidates, start + 1 , curr_target);
return;
}
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
if(candidates.empty()) return res;
sort(candidates.begin(), candidates.end());
vector<int>nums;
helper(nums, candidates, 0, target);
return res;
}
};
```