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:
For example, given candidate set2,3,6,7and target7,
A solution set is:
[7]
[2, 2, 3]
给定一组候选数字(C,是个set)和目标数字T,找到C中的所有唯一组合,其中候选数字总和为T. 可以从C无限次数中选择相同的重复数。
1.首先 从小到大排序(快排)
2.然后回溯法,由于数字set有序,回溯的点:
当加上当前数时,累加的数字之和大于T,因此退一步回到比他小的那个数字上
当加上当前数时,累加的数字之和等于T,当前存放数字序列的集合满足条件,是个解,那再往深的遍历,也没有可用的解了。退到上一步
import java.util.ArrayList;
import java.util.List;
public class Solution {
public ArrayList> combinationSum(int[] candidates, int target) {
ArrayList> resList = new ArrayList<>();
if (candidates == null || candidates.length == 0) {
return resList;
}
qsort(candidates, 0, candidates.length-1);
Integer accu = 0;
List tempRes = new ArrayList<>();
dfs(candidates, target, 0, accu, tempRes, resList);
return resList;
}
private static void dfs(int[] candidates, int target, int start, int accu, List tempRes,
ArrayList> resList) {
for (int i = start; i < candidates.length; ++i) {
// 满足条件
if (accu + candidates[i] == target) {
tempRes.add(candidates[i]);
resList.add(new ArrayList<>(tempRes));
tempRes.remove(tempRes.size() - 1);
return;
}
if (accu + candidates[i] > target) {
return;
}
tempRes.add(candidates[i]);
dfs(candidates, target, i, accu + candidates[i], tempRes, resList);
tempRes.remove(tempRes.size() - 1);
}
}
private static void qsort(int[] candidates, int start, int end) {
if (start >= end) {
return;
}
// 枢轴量
int temp = candidates[start];
int left = start;
int right = end;
while (left < right) {
while (right > left && candidates[right] >= temp) {
--right;
}
if (right > left) {
candidates[left] = candidates[right];
++left;
}
while (right > left && candidates[left] <= temp) {
++left;
}
if (right > left) {
candidates[right] = candidates[left];
--right;
}
}
candidates[left] = temp;
qsort(candidates, start, left - 1);
qsort(candidates, left + 1, end);
}
}
经验和教训
1.在深搜过程中 ,
dfs(candidates, target, i , accu + candidates[i], tempRes, resList);
一开始写start传的是i+1,这样候选数字中的每个数字只能使用一次,改为i后,满足了:The same repeated number may be chosen from C unlimited number of times.
2.多写写堆排序