找出数组中的所有数字之和等于目标值的数组. (可登入LeetCode网站查询 40. 组合总和 II)
[2,5,2,1,2], 5,
1.排序 [2,5,2,1,2] -> 1,2(1),2(2),2(3),5
2. 1,2(1),2(2) = 5
以2(2)为起点走下面循环: 1,2(1),2(2),2(3); 1,2(1),2(2),2(3),5 ; 1,2(1),2(2),2(3) ;1,2(1),2(2),5 此三种组合都一定都大于5 所以直接返回.
以2(3)为起点走下面循环: 因为1,1,2(1),2(2)循环完要走 1,1,2(1),2(3) 因为2(3)走的循环一定在以2(2)为起点的循环中.
public class Solution {
List<List<Integer>> lists = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
// 排序 更好的计算 {4, 1, 1, 4, 4, 2, 3, 5} -> {1, 1, 2, 3, 4, 4, 4, 5} target = 9
// 好处1.起始位置相同无需重新再循环 当下标为 0 ,值为1的,我们所得数组,和下标为1,值1的结果一样
// 好处2.当等于大于目标值的时候,可以结束此次循环. 1,1,3,4, 等于 9 无需去看 1,1,3,5一定大于9
Arrays.sort(candidates);
ArrayList<Integer> objects1 = new ArrayList<>();
getList(objects1, candidates, 0, target);
return lists;
}
private void getList(ArrayList<Integer> list, int[] ints, Integer x, Integer y) {
for (int i = x; i < ints.length; i++) {
// i > x 说明该层循环已经遍历1次,所以重复数据无需遍历 同好处1
// ->循环当前位置 1,1,2,3,4 > 9 结束
// 下次循环 1,1,2,4(此4 下标为4)
// 不会是 1,1,2,2,4(此4 下标为5)
if (i > x && ints[i] == ints[i-1] ){
continue;
}
ArrayList<Integer> clone = (ArrayList<Integer>) list.clone();
if (ints[i] == y) {
clone.add(ints[i]);
lists.add(clone);
// 此如见好处2
// ->循环当前位置 2,3,4 = 9 结束
// 下次循环 2,4,5
// 不会是 2,3,5
return;
} else if (ints[i] < y) {
clone.add(ints[i]);
getList(clone, ints, i + 1, y - ints[i]);
} else {
// 此如见好处2 1, 1, 2, 3, 4, 4, 4, 5
// ->循环当前位置 1,1,2,3,4 > 9 结束
// 下次循环 1,1,2,4
// 不会是 1,1,2,3,5
return;
}
}
}
public static void main(String[] args) {
Solution solution = new Solution();
int[] ints = {4, 1, 1, 4, 4, 2, 3, 5}; //1,2
List<List<Integer>> lists = solution.combinationSum2(ints, 9);
lists.forEach(list -> {
System.out.println("================================");
list.forEach(lst -> {
System.out.print(lst + ",");
});
});
}
}
可见代码注释。