This runs in O(n log n + m log m)
, where n
is the size of first
, and m
is the size of second
. Basically, it sorts the arrays, then pass through each one, adding ones that don't match to the LinkedList
at each opportunity, then makes an array at the end. The earlier revision of this code did not work correctly because the trailing elements in the longer list were not getting added at the end.
public class SetDifference {
public static void main(String... args) {
String[] arrA = {"1", "2", "3", "4", "5", "25", "10"};
String[] arrB = {"1", "2", "10", "4", "30"};
System.out.println(Arrays.toString(differences(arrA, arrB)));
}
public static String[] differences(String[] first, String[] second) {
String[] sortedFirst = Arrays.copyOf(first, first.length); // O(n)
String[] sortedSecond = Arrays.copyOf(second, second.length); // O(m)
Arrays.sort(sortedFirst); // O(n log n)
Arrays.sort(sortedSecond); // O(m log m)
int firstIndex = 0;
int secondIndex = 0;
LinkedList<String> diffs = new LinkedList<String>();
while (firstIndex < sortedFirst.length && secondIndex < sortedSecond.length) { // O(n + m)
int compare = (int) Math.signum(sortedFirst[firstIndex].compareTo(sortedSecond[secondIndex]));
switch(compare) {
case -1:
diffs.add(sortedFirst[firstIndex]);
firstIndex++;
break;
case 1:
diffs.add(sortedSecond[secondIndex]);
secondIndex++;
break;
default:
firstIndex++;
secondIndex++;
}
}
if(firstIndex < sortedFirst.length) {
append(diffs, sortedFirst, firstIndex);
} else if (secondIndex < sortedSecond.length) {
append(diffs, sortedSecond, secondIndex);
}
String[] strDups = new String[diffs.size()];
return diffs.toArray(strDups);
}
private static void append(LinkedList<String> diffs, String[] sortedArray, int index) {
while(index < sortedArray.length) {
diffs.add(sortedArray[index]);
index++;
}
}
}