-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathThreePartition.java
132 lines (111 loc) · 3.74 KB
/
ThreePartition.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* https://www.techiedelight.com/3-partition-problem/
*/
import java.util.Random;
import java.util.Map;
import java.util.HashMap;
class ThreePartition {
private static void checkInput(int[] a) {
if (a == null) {
throw new IllegalArgumentException();
}
}
private static int arraySum(int[] a) {
int sum = 0;
for (int i : a) {
sum += i;
}
return sum;
}
public static boolean recursive(int[] a) {
int sum = arraySum(a);
if (a.length <= 2 || (sum % 3 != 0)) {
return false;
}
return recursive(a, a.length - 1, sum / 3, sum / 3, sum /3);
}
private static boolean recursive(int[] a, int n, int sumA, int sumB, int sumC) {
if (sumA == 0 && sumB == 0 && sumC == 0) {
return true;
}
if (sumA < 0 || sumB < 0 || sumC < 0) {
return false;
}
if (n < 0) {
return false;
}
return recursive(a, n - 1, sumA - a[n], sumB, sumC) ||
recursive(a, n - 1, sumA, sumB - a[n], sumC) ||
recursive(a, n - 1, sumA, sumB, sumC - a[n]);
}
public static boolean topDown(int[] a) {
int sum = arraySum(a);
if (a.length <= 2 || (sum % 3 != 0)) {
return false;
}
Map<String, Boolean> lookup = new HashMap<>();
return topDown(a, a.length - 1, sum / 3, sum / 3, sum /3, lookup);
}
private static boolean topDown(int[] a, int n, int sumA, int sumB, int sumC,
Map<String, Boolean> lookup) {
if (sumA == 0 && sumB == 0 && sumC == 0) {
return true;
}
if (sumA < 0 || sumB < 0 || sumC < 0) {
return false;
}
if (n < 0) {
return false;
}
String key = sumA + "|" + sumB + "|" + sumC + "|" + n;
if (!lookup.containsKey(key)) {
boolean includeInSetA = topDown(a, n - 1, sumA - a[n], sumB, sumC, lookup);
boolean includeInSetB = topDown(a, n - 1, sumA, sumB - a[n], sumC, lookup);
boolean includeInSetC = topDown(a, n - 1, sumA, sumB, sumC - a[n], lookup);
lookup.put(key, includeInSetA || includeInSetB || includeInSetC);
}
return lookup.get(key);
}
}
class Driver {
private static int[] randomArray(int n, int max) {
int[] a = new int[n];
Random rand = new Random();
for (int i = 0; i < n; ++i) {
a[i] = rand.nextInt(max);
}
return a;
}
private static void printArray(int[] a) {
for (int i : a) {
System.out.print(i + " ");
}
System.out.println();
}
private static void test() {
int maxN = 20;
int maxRange = 30;
for (int i = 0; i <= maxN; ++i) {
for (int j = 1; j <= maxRange; ++j) {
int[] a = Driver.randomArray(i, j);
boolean method1 = ThreePartition.recursive(a);
boolean method2 = ThreePartition.topDown(a);
if (method1 != method1) {
System.out.print("Test failed for input: ");
printArray(a);
System.out.println("Recursive : " + method1 + ", top down" + method2);
}
}
}
}
public static void main(String[] args) {
test();
int n = 10;
int max = 10;
int[] a = Driver.randomArray(n, max);
Driver.printArray(a);
System.out.println("Partition in 3 sets with equal sum: ");
System.out.println("Using recursive method : " + ThreePartition.recursive(a));
System.out.println("Using top down method : " + ThreePartition.topDown(a));
}
}