问题描述:
/**
* Given a set of candidate numbers (C) and a target number (T), find all unique
* combinations in C where the candidate numbers sums to T.
*
* The same repeated number may be chosen from C unlimited number of times.
*
* Note:
*
* All numbers (including target) will be positive integers.
*
* Elements in a combination (a1, a2, ... , ak) must be in non-descending order.
* (ie, a1 <= a2 <= ... <= ak).
*
* The solution set must not contain duplicate combinations. For example, given
* candidate set 2,3,6,7 and target 7, A solution set is: [7] [2, 2, 3]
*/
给一组数,和一个目标和,求有几种组合可以到达目标和。给的这组数要为升序排列。而且这组数里面的数可以使用多次。但是不允许有重复的组合出现。具体代码如下:
public static ArrayList> combinationSum(int[] candidates,
int target) {
ArrayList> ret = new ArrayList>();
ArrayList solution = new ArrayList();
Arrays.sort(candidates);
combinationSum(candidates, 0, 0, target, ret, solution);
return ret;
}
private static void combinationSum(int[] candidates, int start, int sum,
int target, ArrayList> ret,
ArrayList solution) {
if (sum == target) {
ret.add(new ArrayList(solution));
return;
}
if (sum > target)
return;
for (int i = start; i < candidates.length; i++) {
solution.add(candidates[i]);
combinationSum(candidates, i, sum + candidates[i], target, ret, solution);
solution.remove(solution.size() - 1);
}
}
//测试代码
public static void main(String args[])
{
int[]candidates = new int[]{2,3,6,7};
ArrayList> result =combinationSum(candidates,7);
for(int i=0;iout.print(result.get(i));
}
}
老规矩,二维数组ret存储结果组合。一维数组result存储结果。
首先对给的数组进行了sort排序,保证非递减排列。
然后在combinationSum()方法中,首先判断得到的和是否等于target,相等,则把结果存储到ret数组中,然后return到for循环中,把result数组的最后一个删除掉,遍历下一个数。
在for循环中,还运用了一次递归。这个在每次结束这一层递归的时候都会从for循环的开始进行,要注意这一点,在调试的时候可以发现,其实这一点容易搞晕。
因为每次在for循环中进入递归,所以每次刚进入递归时都是从开头i=0开始循环的,所以刚开始会有[2,2,2,2]这种情况,然后会把最后一位remove掉因为(其和为8,大于target,要return回去),变为[2,2,2],然后再进行下一次for循环,这次循环就从i=1开始,result数组开始为,[2,2,2,3],[2,2,2,6],[2,2,2,7].注意,这时,这层递归的for循环已经执行完毕,所以要跳出这层递归,再进行新的一轮for循环。然后result就变为,[2,2,2],[2,2,3],[2,2,6],[2,2,7].在这期间,如果有符合条件的就会存储到ret数组中。依次类推。
理解这个for循环+递归,大致是这样的:
result数组格式:[x,x,x,x]
[x1,x2,x3,x4]这是第四层递归,也就是说最里层的,在这一层中,会把x4 for循环一遍来找到合适的组合。
[x1,x2,x3]是第三层递归。x3会被循环一遍
[x1,x2]是第二层递归,x2会被循环一遍
[x1]是最外层的,x1会被循环一遍
每次要跳出这层递归时会连续删除两次的末尾数据,这个在调试时容易搞晕,因为在for循环时会把最后一个remove掉(便于遍历下一个数据),然后跳出这层递归时,会删减一个数字。所以会出现连续两次remove的情况。