If you care about duplicates, use a hash map to index list A, with the key being the element, and the value being a number of how many times that element has been seen.
You iterate through the first and for every element in A and if it does not exist in the map, put it in there with a value of 1, if it already exists in the map, add one to that value.
Next, iterate through B, and if the value exists, subtract 1. If not, put -1 in the value on the table for that element.
Finally, iterate through the map and for any element that has a value != 0, print out as a difference.
private static <T> List<T> intersectArrays(List<T> a, List<T> b) {
Map<T, Long> intersectionCountMap = new HashMap<T, Long>((((Math.max(a.size(), b.size()))*4)/3)+1);
List<T> returnList = new LinkedList<T>();
for(T element : a) {
Long count = intersectionCountMap.get(element);
if (count != null) {
intersectionCountMap.put(element, count+1);
} else {
intersectionCountMap.put(element, 1L);
}
}
for (T element : b) {
Long count = intersectionCountMap.get(element);
if (count != null) {
intersectionCountMap.put(element, count-1);
} else {
intersectionCountMap.put(element, -1L);
}
}
for(T key : intersectionCountMap.keySet()) {
Long count = intersectionCountMap.get(key);
if (count != null && count != 0) {
for(long i = 0; i < count; i++) {
returnList.add(key);
}
}
}
return returnList;
}
This should run in O(n)
, as we're only iterating the Lists each once, and the Map once. The Data structures here used in Java should be efficient, as the HashMap
is constructed with a capacity that can handle the largest size of the lists.
I'm using a LinkedList
for the return as it provides us a way of adding and iterating through a list for our unknown sized intersection.