add intersection for unsorted lists
Changed the way the intersection is computed. An intersection does not return duplicate values. So the result is like a set.
This commit is contained in:
@@ -22,7 +22,6 @@ public final class IntList implements Serializable, Cloneable {
|
||||
// TODO support sublists
|
||||
// TODO add lastIndexOf
|
||||
// TODO remove bounds checks that are handled by java, e.g. negative indices
|
||||
// TODO intersection for unsorted lists
|
||||
|
||||
private static final long serialVersionUID = 2622570032686034909L;
|
||||
|
||||
@@ -361,12 +360,19 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* <p>
|
||||
* This method does not release any memory. Call {@link #trim()} to free unused
|
||||
* memory.
|
||||
* <p>
|
||||
* For a method that computes the intersection of two lists and also removes
|
||||
* duplicate values, see {@link #intersection(IntList, IntList)}.
|
||||
* <p>
|
||||
* The algorithm has a complexity of O(n*log(m)), where n is the length of
|
||||
* {@code this} and m the length of {@code retain}.
|
||||
*
|
||||
* @param retain
|
||||
* the elements to retain
|
||||
* @throws NullPointerException
|
||||
* if the specified {@link IntList} is null
|
||||
* @see #trim()
|
||||
* @see #intersection(IntList, IntList)
|
||||
*/
|
||||
public void retainAll(final IntList retain) {
|
||||
|
||||
@@ -747,8 +753,17 @@ public final class IntList implements Serializable, Cloneable {
|
||||
/**
|
||||
* Returns a list with all elements that are in {@code a} and {@code b}.
|
||||
* <p>
|
||||
* The cardinality of each element will be equal to the minimum of the
|
||||
* cardinality of each element in the given lists.
|
||||
* The cardinality of each element will be equal to one (like in a set). This
|
||||
* method returns a new list. The list can have unused capacity. Consider using
|
||||
* {@link #trim()}.
|
||||
* <p>
|
||||
* See {@link #retainAll(IntList)} for a method that modifies the list and keeps
|
||||
* duplicate values.
|
||||
* <p>
|
||||
* If both lists are sorted, then the complexity is O(n+m), where n is the
|
||||
* length of the first list and m the length of the second list. If at least one
|
||||
* list is not sorted, then the complexity is O(n*log(m)), where n is the length
|
||||
* of the shorter list and m the length of the longer list.
|
||||
*
|
||||
* @param a
|
||||
* a sorted {@link IntList}
|
||||
@@ -758,33 +773,99 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* {@code b}
|
||||
* @throws NullPointerException
|
||||
* if {@code a} or {@code b} is null
|
||||
* @see #retainAll(IntList)
|
||||
* @see #trim()
|
||||
*/
|
||||
public static IntList intersection(final IntList a, final IntList b) {
|
||||
final IntList result = new IntList(Math.min(a.size(), b.size()));
|
||||
final IntList result;
|
||||
|
||||
if (a.isSorted() && b.isSorted()) {
|
||||
int l = 0;
|
||||
int r = 0;
|
||||
|
||||
while (l < a.size() && r < b.size()) {
|
||||
|
||||
final int lv = a.get(l);
|
||||
final int rv = b.get(r);
|
||||
|
||||
if (lv < rv) {
|
||||
l++;
|
||||
} else if (lv > rv) {
|
||||
r++;
|
||||
} else {
|
||||
result.add(lv);
|
||||
l++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
result = intersectionSorted(a, b);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("retainAll on unsorted lists is not yet supported");
|
||||
result = intersectionUnsorted(a, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements an intersection algorithm with O(n+m), where n is the length of
|
||||
* the first list and m the length of the second list.
|
||||
*
|
||||
* @param a
|
||||
* first list
|
||||
* @param b
|
||||
* second list
|
||||
* @return the intersection
|
||||
*/
|
||||
private static IntList intersectionSorted(final IntList a, final IntList b) {
|
||||
final int aSize = a.size();
|
||||
final int bSize = b.size();
|
||||
final IntList result = new IntList(Math.min(aSize, bSize));
|
||||
|
||||
assert a.isSorted() : "first list must be sorted";
|
||||
assert b.isSorted() : "second list must be sorted";
|
||||
|
||||
int l = 0;
|
||||
int r = 0;
|
||||
|
||||
while (l < aSize && r < bSize) {
|
||||
|
||||
final int lv = a.get(l);
|
||||
final int rv = b.get(r);
|
||||
|
||||
if (lv < rv) {
|
||||
l++;
|
||||
} else if (lv > rv) {
|
||||
r++;
|
||||
} else {
|
||||
result.add(lv);
|
||||
do {
|
||||
l++;
|
||||
} while (l < aSize && lv == a.get(l));
|
||||
do {
|
||||
r++;
|
||||
} while (r < bSize && rv == b.get(r));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements an algorithm with O(n*log(m)), where n is the length of the
|
||||
* shorter list and m the length of the longer list.
|
||||
*
|
||||
* @param a
|
||||
* first list
|
||||
* @param b
|
||||
* second list
|
||||
* @return the intersection
|
||||
*/
|
||||
private static IntList intersectionUnsorted(final IntList a, final IntList b) {
|
||||
final int aSize = a.size();
|
||||
final int bSize = b.size();
|
||||
final IntList result;
|
||||
|
||||
if (aSize < bSize) {
|
||||
result = new IntList(Math.min(aSize, bSize));
|
||||
|
||||
assert !a.isSorted() || !b.isSorted() : "at least one list must be unsorted";
|
||||
|
||||
for (int l = 0; l < aSize; l++) {
|
||||
final int lv = a.get(l);
|
||||
|
||||
if (b.indexOf(lv) >= 0) {
|
||||
result.add(lv);
|
||||
}
|
||||
|
||||
while (l + 1 < aSize && lv == a.get(l + 1)) {
|
||||
l++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = intersectionUnsorted(b, a);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user