给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。 对于给定的输入,保证和为 target 的唯一组合数少于 150 个。如输入: candidates = [2,3,6,7], target = 7,输出: [[7],[2,2,3]];如输入: candidates = [2,3,5], target = 8,则输出: [[2,2,2,2],[2,3,3],[3,5]]。
从数组的第0个元素开始,每次遍历到第i个元素时,则有两种可能,一种是直接跳过,一种是试用该元素,但试用该元素肯定有一个前提条件那就是target-candidates[i]必须要大于0,其中target每次循环都要重新赋值。循环结束的条件就是当i已经越界或者已经组合好和为target时。根据这种算法思想实现代码如下。
package likouhot;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
* 39.组合的总和
*/
public class Demo39 {
/*
* 求组合,且数据可以重复,这有点像计算括号对数类似,需要用到递归算法
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> alllist = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
backTrack(alllist,list,candidates,target,0);
return alllist;
}
public void backTrack(List<List<Integer>> list,List<Integer> subList
,int[] candidates,int target,int index) {
if(index >= candidates.length) {
return;
}
if(target == 0) {
list.add(new ArrayList<Integer>(subList));
return;
}
backTrack(list,subList,candidates,target,index+1);
if(target - candidates[index] >= 0) {
subList.add(candidates[index]);
backTrack(list,subList,candidates,target-candidates[index],index);
subList.remove(subList.size()-1);
}
}
public static void main(String args[]) {
Demo39 demo = new Demo39();
int[] candidates = {2,3,5};
int target = 8;
List<List<Integer>> list = demo.combinationSum(candidates, target);
int length = list.size();
for(int i=0;i<length;i++) {
List<Integer> subList = list.get(i);
System.out.println(Arrays.toString(subList.toArray()));
}
}
}