40. 组合总和 II
题目描述查看:https://leetcode-cn.com/problems/combination-sum-ii/
题目的意思是从一个给定的数组中,选出一些数,这些数的和是target。
与39题的区别是,数组中存在重复元素,但是选数的时候不会选选过的数。
1.回溯法
-
思路
找到回溯结束条件,回溯参数。
回溯结束条件
target递减到0以下;target为0,说明是一个结果,保存到结果集里。
1 if(target < 0)return; 2 else if(target == 0){ 3 res.add(new ArrayList<>(choose)); 4 }
回溯参数
target:累加目标值
choose:已选值
candidates:还能选哪些值
res:符合题目要求的值
begain:避免仅位置颠倒的重复遍历。
private static void combinationSumHelper2(int target,List<Integer> choose,int[] candidates,List<List<Integer>> res,int begain)
-
边界条件
由于数组中存在重复元素,如[2,2,2,2,3],已选数组[2],下一个选择,不管选其后的哪个2,结果都是[2,2],避免重复结果,直接跳过。
if(i > begain && candidates[i] == candidates[i-1]) continue ;
-
代码
1 public List<List<Integer>> combinationSum2(int[] candidates, int target) { 2 List<List<Integer>> res = new ArrayList<>(); 3 Arrays.sort(candidates); 4 List<Integer> choose = new ArrayList<>(); 5 combinationSumHelper2(target,choose,candidates,res,0); 6 return res; 7 } 8 9 private void combinationSumHelper2(int target,List<Integer> choose,int[] candidates,List<List<Integer>> res,int begain){ 10 if(target < 0)return; 11 else if(target == 0){ 12 res.add(new ArrayList<>(choose)); 13 } 14 15 for (int i = begain; i < candidates.length; i++) { 16 if(i > begain && candidates[i] == candidates[i-1]) continue ; 17 choose.add(candidates[i]); 18 int[] remainder = new int[candidates.length -1]; 19 for (int j = 1; j < candidates.length; j++) { 20 remainder[j-1] = candidates[j]; 21 } 22 combinationSumHelper2(target-candidates[i],choose,remainder,res,i); 23 choose.remove(choose.size()-1); 24 } 25 }