Skip to content

Commit

Permalink
17.18: Some code cleanup + adding new solution for problem
Browse files Browse the repository at this point in the history
  • Loading branch information
Gayle McDowell committed Nov 10, 2018
1 parent 5ee7990 commit f88b754
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 35 deletions.
3 changes: 3 additions & 0 deletions Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionA.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public static Range shortestSupersequence(int[] bigArray, int[] smallArray) {
bestEnd = end;
}
}
if (bestStart < 0 || bestEnd < 0) {
return null;
}
return new Range(bestStart, bestEnd);
}

Expand Down
3 changes: 3 additions & 0 deletions Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionB.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public static Range getShortestClosure(int[] closures) {
bestEnd = closures[i];
}
}
if (bestStart < 0 || bestEnd < 0) {
return null;
}
return new Range(bestStart, bestEnd);
}

Expand Down
38 changes: 22 additions & 16 deletions Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionC.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

public class QuestionC {

public static Range shortestSupersequence(int[] big, int[] small) {
int[] closures = getClosures(big, small);
return getShortestClosure(closures);
}

/* Get closure for each index. */
public static int[] getClosures(int[] big, int[] small) {
int[] closure = new int[big.length];
for (int i = 0; i < small.length; i++) {
sweepForClosure(big, closure, small[i]);
}
return closure;
}

/* Do backwards sweep and update the closures list with the next occurrence of value, if it's later than the current closure*/
public static void sweepForClosure(int[] big, int[] closures, int value) {
int next = -1;
Expand All @@ -15,17 +29,9 @@ public static void sweepForClosure(int[] big, int[] closures, int value) {
}
}

/* Get closure for each index. */
public static int[] getClosures(int[] big, int[] small) {
int[] closure = new int[big.length];
for (int i = 0; i < small.length; i++) {
sweepForClosure(big, closure, small[i]);
}
return closure;
}

/* Get shortest closure. */
public static Range getShortestClosure(int[] closures) {
if (closures == null || closures.length == 0) return null;
Range shortest = new Range(0, closures[0]);
for (int i = 1; i < closures.length; i++) {
if (closures[i] == -1) {
Expand All @@ -36,20 +42,20 @@ public static Range getShortestClosure(int[] closures) {
shortest = range;
}
}
if (shortest.length() <= 0) return null;
return shortest;
}

public static Range shortestSupersequence(int[] big, int[] small) {
int[] closures = getClosures(big, small);
return getShortestClosure(closures);
}

public static void main(String[] args) {
int[] array = {7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 9, 7};
int[] array = {9, 2, 4, 6, 2, 5, 9};
int[] set = {1, 5, 9};
System.out.println(array.length);
Range shortest = shortestSupersequence(array, set);
System.out.println(shortest.getStart() + ", " + shortest.getEnd());
if (shortest == null) {
System.out.println("No valid subsequence.");
} else {
System.out.println(shortest.getStart() + ", " + shortest.getEnd());
}

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ public static Range getShortestClosure(ArrayList<Queue<Integer>> lists) {

/* Insert min element from each list. */
for (int i = 0; i < lists.size(); i++) {
int head = lists.get(i).remove();
Queue<Integer> list = lists.get(i);
if (list == null || list.size() == 0) {
return null;
}
int head = list.remove();
minHeap.add(new HeapNode(head, i));
max = Math.max(max, head);
}
Expand Down
94 changes: 94 additions & 0 deletions Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/QuestionE.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package Q17_18_Shortest_Supersequence;

import java.util.HashMap;

public class QuestionE {
/* CountedLookup acts a simple hash table with increment/decrement functions
* which can efficiently tell you how many values in the hash table are
* at least one.
*/
public static class CountedLookup {
HashMap<Integer, Integer> lookup = new HashMap<Integer, Integer>();
int fulfilled = 0;
public CountedLookup(int[] array) {
for (int a : array) {
lookup.put(a, 0);
}
}

public boolean contains(int v) {
return lookup.containsKey(v);
}

public void incrementIfFound(int v) {
if (!contains(v)) return;
if (lookup.getOrDefault(v, 0) == 0) {
fulfilled += 1;
}
lookup.put(v, lookup.getOrDefault(v, 0) + 1);
}

public void decrementIfFound(int v) {
if (!contains(v)) return;
lookup.put(v, lookup.getOrDefault(v, 0) - 1);
if (lookup.getOrDefault(v, 0) == 0) {
fulfilled -= 1;
}
}

public boolean areAllFulfilled() {
return fulfilled == lookup.keySet().size();
}
}

/* Find shortest subarray which contains all elements from small. */
public static Range shortestSupersequence(int[] big, int[] small) {
if (big.length < small.length) return null;

CountedLookup countedLookup = new CountedLookup(small);
Range best = null;
int right = 0;
countedLookup.incrementIfFound(big[0]); // Take in left
for (int left = 0; left < big.length; left++) {
right = findClosure(big, right, countedLookup); // Move right to closure end
if (!countedLookup.areAllFulfilled()) { // No closure -> break
break;
}

/* Update biggest range. */
int length = right - left + 1;
if (best == null || best.length() > length) {
best = new Range(left, right);
}
countedLookup.decrementIfFound(big[left]); // Drop leftmost element
}
return best;
}

/* Find closure for index, and update countedlookup */
public static int findClosure(int[] big, int startIndex, CountedLookup countedLookup) {
int index = startIndex;

/* Move forward until everything is fulfilled. */
while (!countedLookup.areAllFulfilled() && index + 1 < big.length) {
index++;
countedLookup.incrementIfFound(big[index]);
}
return index;
}

public static void main(String[] args) {
int[] array = {7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 8, 9, 7};
int[] set = {1, 5, 9};
Range shortest = shortestSupersequence(array, set);
if (shortest == null) {
System.out.println("not found");
} else {
System.out.println(shortest.toString());
for (int i = shortest.getStart(); i <= shortest.getEnd(); i++) {
System.out.print(array[i] + ", ");
}
}
}

}
30 changes: 30 additions & 0 deletions Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/Range.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,36 @@ public int length() {
return end - start + 1;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + end;
result = prime * result + start;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Range other = (Range) obj;
if (end != other.end)
return false;
if (start != other.start)
return false;
return true;
}

@Override
public String toString() {
return "Range [start=" + start + ", end=" + end + "]";
}

public boolean shorterThan(Range other) {
return length() < other.length();
}
Expand Down
57 changes: 39 additions & 18 deletions Java/Ch 17. Hard/Q17_18_Shortest_Supersequence/Tester.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
package Q17_18_Shortest_Supersequence;

public class Tester {
import CtCILibrary.AssortedMethods;

/**
* @param args
*/
public static void main(String[] args) {
int[] array = {9, 5, 1, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 9, 7};
int[] set = {1, 5, 9};

Range shortestA = QuestionA.shortestSupersequence(array, set);
Range shortestB = QuestionB.shortestSupersequence(array, set);
Range shortestC = QuestionC.shortestSupersequence(array, set);
Range shortestD = QuestionD.shortestSupersequence(array, set);
public class Tester {
public static boolean equivalent(Range[] ranges) {
if (ranges[0] == null) {
for (Range r : ranges) {
if (r != null) return false;
}
return true;
}

int targetLength = ranges[0].length();
for (Range r : ranges) {
int length = r == null ? 0 : r.length();
if (targetLength != length) {
return false;
}
}

if (shortestA.length() != shortestB.length() ||
shortestB.length() != shortestC.length() ||
shortestC.length() != shortestD.length()) {
System.out.println("Mismatching.");
} else {
System.out.println("Matching: " + shortestA.length());
return true;
}


public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
int[] array = AssortedMethods.randomArray(i, 0, 15);
int[] set = {0, 5, 8, 10};

Range[] ranges = new Range[5];

ranges[0] = QuestionA.shortestSupersequence(array, set);
ranges[1] = QuestionB.shortestSupersequence(array, set);
ranges[2] = QuestionC.shortestSupersequence(array, set);
ranges[3] = QuestionD.shortestSupersequence(array, set);
ranges[4] = QuestionE.shortestSupersequence(array, set);

if (!equivalent(ranges)) {
System.out.println("Mismatching.");
} else {
int length = ranges[0] == null ? 0 : ranges[0].length();
System.out.println("Matching: " + length);
}
}
}

Expand Down

0 comments on commit f88b754

Please sign in to comment.