40.Combination Sum II
给定一个数组,给定一个目标值,求数组中的元素之和等于目标值的组合。数组中的元素不能重复使用,但数组中有重复的元素。
Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
思路:
和39题(Combination Sum)类似,区别在于39题的元素可以重复利用,而此题不能重复使用,且此题有重复的元素。结题方法还是使用递归,但递归调用的时候从下一个值得地方开始,且当此元素与前一个元素值相等时,跳过。
class Solution { public: vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { vector<vector<int>> res; sort(candidates.begin(), candidates.end()); int n = candidates.size(); for (int i = 0; i < n; i++) { if (i > 0 && candidates[i] == candidates[i - 1]) continue; if (candidates[i] > target) break; if (candidates[i] == target) { res.push_back({ candidates[i] }); break; } vector<int> tmp(candidates.begin() + i + 1, candidates.end()); vector<vector<int>> tmp_res = combinationSum2(tmp, target - candidates[i]); int tmp_res_len = tmp_res.size(); for (int j = 0; j < tmp_res_len; j++) { tmp_res[j].insert(tmp_res[j].begin(), candidates[i]); res.push_back(tmp_res[j]); } } return res; } };
Java 版:
class Solution { public List<List<Integer>> combinationSum2(int[] candidates, int target) { Arrays.sort(candidates); List<List<Integer>> res = new ArrayList<>(); this.combinationSum2DFS(candidates, target, 0, new ArrayList<Integer>(), res); return res; } public void combinationSum2DFS(int[] candidates, int target, int begin, List<Integer> tmp, List<List<Integer>> res){ if(target == 0){ res.add(new ArrayList(tmp)); return; } for(int i = begin; i < candidates.length; i++){ if( i > begin && candidates[i] == candidates[i - 1]) continue; //重点理解这儿的去重,为什么是 i > begin if(target - candidates[i] < 0) break; tmp.add(candidates[i]); this.combinationSum2DFS(candidates, target - candidates[i], i + 1, tmp, res); if(tmp.size() > 0) tmp.remove(tmp.size() - 1); } } }