-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCombinationSum3.java
117 lines (96 loc) · 3.29 KB
/
CombinationSum3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package org.sean.backtracking;
import java.util.*;
import java.util.stream.Collectors;
/**
* 216. Combination Sum III
*/
public class CombinationSum3 {
List<Set<List<Integer>>> caches;
// k numbers that add up to a number n
public List<List<Integer>> combinationSum30(int k, int n) {
int[] candidates = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
int maxSum = 0;
for (int i : candidates) {
maxSum += i;
}
if (n > maxSum || n < 1) {
return Collections.emptyList();
}
caches = new ArrayList<>(n + 1);
caches.add(Collections.emptySet()); // 0
int length = candidates.length;
for (int i = 1; i <= n; i++) {
Set<List<Integer>> listResult = new HashSet<>();
for (int j = 0; j < length; j++) {
int w = candidates[j];
if (i == w) {
listResult.add(Arrays.asList(w));
} else if (i > w) {
int diff = i - w;
reduceSet(listResult, w, diff);
} else {
break;
}
}
caches.add(listResult);
}
Set<List<Integer>> result = caches.get(n);
return result.stream().filter(integers -> integers.size() == k).collect(Collectors.toList());
}
private void reduceSet(Set<List<Integer>> dpOut, int candidate, int rest) {
if (rest > 0) { // skip <= 0
Set<List<Integer>> sets = caches.get(rest);
if (sets != null) {
for (List<Integer> set : sets) {
// without duplicate elem
Set<Integer> existedSet = new HashSet<>(set);
if (existedSet.contains(candidate)) {
continue;
}
List<Integer> matchedOut = new ArrayList<>(set);
matchedOut.add(candidate);
// !!n*lg(n)
Collections.sort(matchedOut);
dpOut.add(matchedOut);
}
}
}
}
// region DFS
private int[] nums;
boolean[] used;
List<List<Integer>> out = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
nums = new int[9];
used = new boolean[nums.length + 1]; // [0-9]
for (int i = 0; i < 9; i++) {
nums[i] = i + 1;
}
int sum = Arrays.stream(nums).sum();
if (n > sum || n < 1)
return Collections.emptyList();
search(nums, 0, n, k, new ArrayList<>());
return out;
}
private void search(int[] nums, int pos, int targetSum, int k, List<Integer> curr) {
if (0 == targetSum && curr.size() == k) {
out.add(new ArrayList<>(curr));
return;
}
if (targetSum < 0)
return;
if (pos >= nums.length || curr.size() > k)
return;
for (int i = pos; i < nums.length; i++) {
int elem = nums[i];
if (used[elem])
continue;
curr.add(elem);
used[elem] = true;
search(nums, i + 1, targetSum - elem, k, curr);
curr.remove(curr.size() - 1);
used[elem] = false;
}
}
// endregion
}