第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] ]
二、思路
总体采用先递归回溯找到所有的可能值,然后进行去重处理
1.在递归过程中,对递归函数的构建(全局变量list存储可能值,nowData值存储某一个对象中的一系列值,number记录下一步需要添加的值,candidates数组,target目标值);
2.在递归函数中,我的思路是首先判断存储的nowData值是否符合目标值,如果符合则添加到全局变量中,如果不符合,再判断是否小于目标值。
3.小于目标值则继续添加下一个数字进行递归。
4.大于目标值则直接结束该递归函数
5.对于去重,直接使用set表进行去重,因为set表进行去重
三、代码
public List<List<Integer>> combinationSum2(int[] candidates, int target) { List<List<Integer>> temp=new ArrayList<List<Integer>>(); Arrays.sort(candidates); for(int q=0;q<candidates.length;q++) { FindAll(temp, String.valueOf(candidates[q]), q+1, candidates, target); } //利用set去重 Set<List<Integer>> alltemp=new HashSet<List<Integer>>(); alltemp.addAll(temp); temp.clear(); temp.addAll(alltemp); return temp; } //使用回溯算法 public void FindAll( List<List<Integer>> temp,String nowData,int number,int[]candidates,int target) { String [] nd=nowData.split(","); int com=0; for(int i=0;i<nd.length;i++) { com=Integer.parseInt(nd[i])+com; } if(com==target) { //将记录的值转换为int类型并保存至数组中 List<Integer> smalltemp=new ArrayList<Integer>(); for(int j=0;j<nd.length;j++) { smalltemp.add(Integer.parseInt(nd[j])); } temp.add(smalltemp); } else if(com>target) { return; } else { if(number>=candidates.length) { return; } else { for(int i=number;i<candidates.length;i++) { FindAll(temp, nowData+","+candidates[i], i+1, candidates, target); } } } }