-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCombinationSum2.java
91 lines (69 loc) · 2.47 KB
/
CombinationSum2.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
package org.sean.backtracking;
import java.util.*;
/** * 40. Combination Sum II */
public class CombinationSum2 {
List<Set<List<Integer>>> caches = new ArrayList<>();
// The original valid element table
private int[] table;
private int[] tmp;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if (candidates == null || candidates.length == 0 || target == 0)
return Collections.emptyList();
int len = candidates.length;
table = new int[target + 1];
for (int i = 0; i < len; i++) {
int elem = candidates[i];
if (elem <= target) {
table[elem] += 1;
}
}
tmp = new int[target + 1];
caches = new ArrayList<>(target + 1);
caches.add(Collections.emptySet());
int length = candidates.length;
for (int i = 1; i <= target; i++) {
Set<List<Integer>> dp = new HashSet<>();
for (int j = 0; j < length; j++) {
int candidate = candidates[j];
if (i == candidate) {
dp.add(new ArrayList<>(Arrays.asList(i)));
} else if (i > candidate) { // >
reduceSet(dp, candidate, i - candidate);
}
}
caches.add(dp);
}
Set<List<Integer>> result = caches.get(target);
return new LinkedList<>(result);
}
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) {
List<Integer> matchedOut = new ArrayList<>(set);
matchedOut.add(candidate);
// check for a group of limited elements
boolean result = limitReached(matchedOut);
if (result) continue;
// !!n*lg(n)
Collections.sort(matchedOut);
dpOut.add(matchedOut);
}
}
}
}
private boolean limitReached(List<Integer> matchedOut) {
Arrays.fill(tmp, 0);
for (Integer i : matchedOut) {
tmp[i] += 1;
}
int last = tmp.length - 1;
for (int p = 0; p <= last; p++) {
if (tmp[p] > table[p]) {
return true;
}
}
return false;
}
}