Skip to content

Commit f88b754

Browse files
author
Gayle McDowell
committed
17.18: Some code cleanup + adding new solution for problem
1 parent 5ee7990 commit f88b754

File tree

7 files changed

+196
-35
lines changed

7 files changed

+196
-35
lines changed

Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionA.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public static Range shortestSupersequence(int[] bigArray, int[] smallArray) {
3737
bestEnd = end;
3838
}
3939
}
40+
if (bestStart < 0 || bestEnd < 0) {
41+
return null;
42+
}
4043
return new Range(bestStart, bestEnd);
4144
}
4245

Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionB.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public static Range getShortestClosure(int[] closures) {
6060
bestEnd = closures[i];
6161
}
6262
}
63+
if (bestStart < 0 || bestEnd < 0) {
64+
return null;
65+
}
6366
return new Range(bestStart, bestEnd);
6467
}
6568

Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionC.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
public class QuestionC {
44

5+
public static Range shortestSupersequence(int[] big, int[] small) {
6+
int[] closures = getClosures(big, small);
7+
return getShortestClosure(closures);
8+
}
9+
10+
/* Get closure for each index. */
11+
public static int[] getClosures(int[] big, int[] small) {
12+
int[] closure = new int[big.length];
13+
for (int i = 0; i < small.length; i++) {
14+
sweepForClosure(big, closure, small[i]);
15+
}
16+
return closure;
17+
}
18+
519
/* Do backwards sweep and update the closures list with the next occurrence of value, if it's later than the current closure*/
620
public static void sweepForClosure(int[] big, int[] closures, int value) {
721
int next = -1;
@@ -15,17 +29,9 @@ public static void sweepForClosure(int[] big, int[] closures, int value) {
1529
}
1630
}
1731

18-
/* Get closure for each index. */
19-
public static int[] getClosures(int[] big, int[] small) {
20-
int[] closure = new int[big.length];
21-
for (int i = 0; i < small.length; i++) {
22-
sweepForClosure(big, closure, small[i]);
23-
}
24-
return closure;
25-
}
26-
2732
/* Get shortest closure. */
2833
public static Range getShortestClosure(int[] closures) {
34+
if (closures == null || closures.length == 0) return null;
2935
Range shortest = new Range(0, closures[0]);
3036
for (int i = 1; i < closures.length; i++) {
3137
if (closures[i] == -1) {
@@ -36,20 +42,20 @@ public static Range getShortestClosure(int[] closures) {
3642
shortest = range;
3743
}
3844
}
45+
if (shortest.length() <= 0) return null;
3946
return shortest;
4047
}
4148

42-
public static Range shortestSupersequence(int[] big, int[] small) {
43-
int[] closures = getClosures(big, small);
44-
return getShortestClosure(closures);
45-
}
46-
4749
public static void main(String[] args) {
48-
int[] array = {7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 9, 7};
50+
int[] array = {9, 2, 4, 6, 2, 5, 9};
4951
int[] set = {1, 5, 9};
5052
System.out.println(array.length);
5153
Range shortest = shortestSupersequence(array, set);
52-
System.out.println(shortest.getStart() + ", " + shortest.getEnd());
54+
if (shortest == null) {
55+
System.out.println("No valid subsequence.");
56+
} else {
57+
System.out.println(shortest.getStart() + ", " + shortest.getEnd());
58+
}
5359

5460
}
5561

Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionD.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ public static Range getShortestClosure(ArrayList<Queue<Integer>> lists) {
1717

1818
/* Insert min element from each list. */
1919
for (int i = 0; i < lists.size(); i++) {
20-
int head = lists.get(i).remove();
20+
Queue<Integer> list = lists.get(i);
21+
if (list == null || list.size() == 0) {
22+
return null;
23+
}
24+
int head = list.remove();
2125
minHeap.add(new HeapNode(head, i));
2226
max = Math.max(max, head);
2327
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package Q17_18_Shortest_Supersequence;
2+
3+
import java.util.HashMap;
4+
5+
public class QuestionE {
6+
/* CountedLookup acts a simple hash table with increment/decrement functions
7+
* which can efficiently tell you how many values in the hash table are
8+
* at least one.
9+
*/
10+
public static class CountedLookup {
11+
HashMap<Integer, Integer> lookup = new HashMap<Integer, Integer>();
12+
int fulfilled = 0;
13+
public CountedLookup(int[] array) {
14+
for (int a : array) {
15+
lookup.put(a, 0);
16+
}
17+
}
18+
19+
public boolean contains(int v) {
20+
return lookup.containsKey(v);
21+
}
22+
23+
public void incrementIfFound(int v) {
24+
if (!contains(v)) return;
25+
if (lookup.getOrDefault(v, 0) == 0) {
26+
fulfilled += 1;
27+
}
28+
lookup.put(v, lookup.getOrDefault(v, 0) + 1);
29+
}
30+
31+
public void decrementIfFound(int v) {
32+
if (!contains(v)) return;
33+
lookup.put(v, lookup.getOrDefault(v, 0) - 1);
34+
if (lookup.getOrDefault(v, 0) == 0) {
35+
fulfilled -= 1;
36+
}
37+
}
38+
39+
public boolean areAllFulfilled() {
40+
return fulfilled == lookup.keySet().size();
41+
}
42+
}
43+
44+
/* Find shortest subarray which contains all elements from small. */
45+
public static Range shortestSupersequence(int[] big, int[] small) {
46+
if (big.length < small.length) return null;
47+
48+
CountedLookup countedLookup = new CountedLookup(small);
49+
Range best = null;
50+
int right = 0;
51+
countedLookup.incrementIfFound(big[0]); // Take in left
52+
for (int left = 0; left < big.length; left++) {
53+
right = findClosure(big, right, countedLookup); // Move right to closure end
54+
if (!countedLookup.areAllFulfilled()) { // No closure -> break
55+
break;
56+
}
57+
58+
/* Update biggest range. */
59+
int length = right - left + 1;
60+
if (best == null || best.length() > length) {
61+
best = new Range(left, right);
62+
}
63+
countedLookup.decrementIfFound(big[left]); // Drop leftmost element
64+
}
65+
return best;
66+
}
67+
68+
/* Find closure for index, and update countedlookup */
69+
public static int findClosure(int[] big, int startIndex, CountedLookup countedLookup) {
70+
int index = startIndex;
71+
72+
/* Move forward until everything is fulfilled. */
73+
while (!countedLookup.areAllFulfilled() && index + 1 < big.length) {
74+
index++;
75+
countedLookup.incrementIfFound(big[index]);
76+
}
77+
return index;
78+
}
79+
80+
public static void main(String[] args) {
81+
int[] array = {7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 8, 9, 7};
82+
int[] set = {1, 5, 9};
83+
Range shortest = shortestSupersequence(array, set);
84+
if (shortest == null) {
85+
System.out.println("not found");
86+
} else {
87+
System.out.println(shortest.toString());
88+
for (int i = shortest.getStart(); i <= shortest.getEnd(); i++) {
89+
System.out.print(array[i] + ", ");
90+
}
91+
}
92+
}
93+
94+
}

Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/Range.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,36 @@ public int length() {
1212
return end - start + 1;
1313
}
1414

15+
@Override
16+
public int hashCode() {
17+
final int prime = 31;
18+
int result = 1;
19+
result = prime * result + end;
20+
result = prime * result + start;
21+
return result;
22+
}
23+
24+
@Override
25+
public boolean equals(Object obj) {
26+
if (this == obj)
27+
return true;
28+
if (obj == null)
29+
return false;
30+
if (getClass() != obj.getClass())
31+
return false;
32+
Range other = (Range) obj;
33+
if (end != other.end)
34+
return false;
35+
if (start != other.start)
36+
return false;
37+
return true;
38+
}
39+
40+
@Override
41+
public String toString() {
42+
return "Range [start=" + start + ", end=" + end + "]";
43+
}
44+
1545
public boolean shorterThan(Range other) {
1646
return length() < other.length();
1747
}

Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/Tester.java

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,47 @@
11
package Q17_18_Shortest_Supersequence;
22

3-
public class Tester {
3+
import CtCILibrary.AssortedMethods;
44

5-
/**
6-
* @param args
7-
*/
8-
public static void main(String[] args) {
9-
int[] array = {9, 5, 1, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 9, 7};
10-
int[] set = {1, 5, 9};
11-
12-
Range shortestA = QuestionA.shortestSupersequence(array, set);
13-
Range shortestB = QuestionB.shortestSupersequence(array, set);
14-
Range shortestC = QuestionC.shortestSupersequence(array, set);
15-
Range shortestD = QuestionD.shortestSupersequence(array, set);
5+
public class Tester {
6+
public static boolean equivalent(Range[] ranges) {
7+
if (ranges[0] == null) {
8+
for (Range r : ranges) {
9+
if (r != null) return false;
10+
}
11+
return true;
12+
}
1613

14+
int targetLength = ranges[0].length();
15+
for (Range r : ranges) {
16+
int length = r == null ? 0 : r.length();
17+
if (targetLength != length) {
18+
return false;
19+
}
20+
}
1721

18-
if (shortestA.length() != shortestB.length() ||
19-
shortestB.length() != shortestC.length() ||
20-
shortestC.length() != shortestD.length()) {
21-
System.out.println("Mismatching.");
22-
} else {
23-
System.out.println("Matching: " + shortestA.length());
22+
return true;
23+
}
24+
25+
26+
public static void main(String[] args) {
27+
for (int i = 0; i < 100; i++) {
28+
int[] array = AssortedMethods.randomArray(i, 0, 15);
29+
int[] set = {0, 5, 8, 10};
30+
31+
Range[] ranges = new Range[5];
32+
33+
ranges[0] = QuestionA.shortestSupersequence(array, set);
34+
ranges[1] = QuestionB.shortestSupersequence(array, set);
35+
ranges[2] = QuestionC.shortestSupersequence(array, set);
36+
ranges[3] = QuestionD.shortestSupersequence(array, set);
37+
ranges[4] = QuestionE.shortestSupersequence(array, set);
38+
39+
if (!equivalent(ranges)) {
40+
System.out.println("Mismatching.");
41+
} else {
42+
int length = ranges[0] == null ? 0 : ranges[0].length();
43+
System.out.println("Matching: " + length);
44+
}
2445
}
2546
}
2647

0 commit comments

Comments
 (0)