removeAll is now O(n+m) if both lists are sorted
This commit is contained in:
@@ -17,6 +17,7 @@ import java.util.stream.StreamSupport;
|
||||
*/
|
||||
public final class IntList implements Serializable, Cloneable {
|
||||
|
||||
// TODO retainAll on sorted lists
|
||||
// TODO support Iterator
|
||||
// TODO add mod counts
|
||||
// TODO support sublists
|
||||
@@ -433,18 +434,43 @@ public final class IntList implements Serializable, Cloneable {
|
||||
* This method does not release any memory. Call {@link #trim()} to free unused
|
||||
* memory.
|
||||
* <p>
|
||||
* If {@code retain} is sorted, then 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}. If {@code retain} is not sorted, then the complexity is
|
||||
* O(n*m).
|
||||
* If both lists are sorted, then the algorithms has time complexity of O(n+m),
|
||||
* where n is the length of {@code this} and m the length of {@code remove}. If
|
||||
* only {@code remove} is sorted, then the algorithm has a complexity of
|
||||
* O(n*log(m)). If {@code remove} is not sorted, then the complexity is O(n*m).
|
||||
* The space complexity is constant in all cases.
|
||||
*
|
||||
* @param remove the elements to remove
|
||||
* @throws NullPointerException if the specified {@link IntList} is null
|
||||
* @see #trim()
|
||||
*/
|
||||
public void removeAll(final IntList remove) {
|
||||
|
||||
if (isSorted() && remove.isSorted()) {
|
||||
removeSorted(remove);
|
||||
} else {
|
||||
removeIf((val, index) -> remove.indexOf(val) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSorted(final IntList remove) {
|
||||
int posInRemoveList = 0;
|
||||
int insertPosition = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int current = data[i];
|
||||
|
||||
while (posInRemoveList < remove.size() && remove.get(posInRemoveList) < current) {
|
||||
posInRemoveList++;
|
||||
}
|
||||
|
||||
if (posInRemoveList >= remove.size() || remove.get(posInRemoveList) != current) {
|
||||
// keep current element
|
||||
data[insertPosition] = current;
|
||||
insertPosition++;
|
||||
}
|
||||
}
|
||||
size = insertPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements that match the given predicate.
|
||||
|
||||
@@ -423,18 +423,43 @@ public final class LongList implements Serializable, Cloneable {
|
||||
* This method does not release any memory. Call {@link #trim()} to free unused
|
||||
* memory.
|
||||
* <p>
|
||||
* If {@code retain} is sorted, then 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}. If {@code retain} is not sorted, then the complexity is
|
||||
* O(n*m).
|
||||
* If both lists are sorted, then the algorithms has time complexity of O(n+m),
|
||||
* where n is the length of {@code this} and m the length of {@code remove}. If
|
||||
* only {@code remove} is sorted, then the algorithm has a complexity of
|
||||
* O(n*log(m)). If {@code remove} is not sorted, then the complexity is O(n*m).
|
||||
* The space complexity is constant in all cases.
|
||||
*
|
||||
* @param remove the elements to remove
|
||||
* @throws NullPointerException if the specified {@link LongList} is null
|
||||
* @see #trim()
|
||||
*/
|
||||
public void removeAll(final LongList remove) {
|
||||
|
||||
if (isSorted() && remove.isSorted()) {
|
||||
removeSorted(remove);
|
||||
} else {
|
||||
removeIf((val, index) -> remove.indexOf(val) >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSorted(final LongList remove) {
|
||||
int posInRemoveList = 0;
|
||||
int insertPosition = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
final long current = data[i];
|
||||
|
||||
while (posInRemoveList < remove.size() && remove.get(posInRemoveList) < current) {
|
||||
posInRemoveList++;
|
||||
}
|
||||
|
||||
if (posInRemoveList >= remove.size() || remove.get(posInRemoveList) != current) {
|
||||
// keep current element
|
||||
data[insertPosition] = current;
|
||||
insertPosition++;
|
||||
}
|
||||
}
|
||||
size = insertPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements that match the given predicate.
|
||||
|
||||
@@ -1114,6 +1114,28 @@ public class IntListTest {
|
||||
Assertions.assertEquals(0, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllFromSortedList() {
|
||||
final IntList list = IntList.of(1, 2, 3, 4, 5);
|
||||
final IntList remove = IntList.of(1, 3);
|
||||
|
||||
list.removeAll(remove);
|
||||
Assertions.assertArrayEquals(new int[] { 2, 4, 5 }, list.toArray());
|
||||
Assertions.assertEquals(3, list.size());
|
||||
Assertions.assertTrue(list.isSorted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllFromSortedList2() {
|
||||
final IntList list = IntList.of(2, 4, 4, 6, 8);
|
||||
final IntList remove = IntList.of(1, 4, 9);
|
||||
|
||||
list.removeAll(remove);
|
||||
Assertions.assertArrayEquals(new int[] { 2, 6, 8 }, list.toArray());
|
||||
Assertions.assertEquals(3, list.size());
|
||||
Assertions.assertTrue(list.isSorted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetainAll() {
|
||||
final IntList list = IntList.of(-2, -1, 0, 1, 2, 3, 4, 5, 6);
|
||||
|
||||
@@ -1104,6 +1104,28 @@ public class LongListTest {
|
||||
Assertions.assertEquals(0, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllFromSortedList() {
|
||||
final LongList list = LongList.of(1, 2, 3, 4, 5);
|
||||
final LongList remove = LongList.of(1, 3);
|
||||
|
||||
list.removeAll(remove);
|
||||
Assertions.assertArrayEquals(new long[] { 2, 4, 5 }, list.toArray());
|
||||
Assertions.assertEquals(3, list.size());
|
||||
Assertions.assertTrue(list.isSorted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllFromSortedList2() {
|
||||
final LongList list = LongList.of(2, 4, 4, 6, 8);
|
||||
final LongList remove = LongList.of(1, 4, 9);
|
||||
|
||||
list.removeAll(remove);
|
||||
Assertions.assertArrayEquals(new long[] { 2, 6, 8 }, list.toArray());
|
||||
Assertions.assertEquals(3, list.size());
|
||||
Assertions.assertTrue(list.isSorted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetainAll() {
|
||||
final LongList list = LongList.of(-2, -1, 0, 1, 2, 3, 4, 5, 6);
|
||||
|
||||
Reference in New Issue
Block a user