简体   繁体   中英

Fastest way to remove an element from an array?

I've coded an algorithm designed to produce a list of the closest triplets from three sorted arrays (one element contributed by each array). The algorithm finds the closest triplet, removes those elements, then repeats the process. The algorithm itself runs quite fast, however the code I'm using to "remove" the elements from each array slows it down significantly. Is there a more efficient method, or is random removal necessarily always O(n)?

My current strategy (effectively identical to std::move ):

for(int i = 6; i < n; ++i)
        array[i] = array[i+1];

Where n is the size of the array, and 6 is the index of the element to be removed.

Fastest way to remove an element from an array?

Note that there is no way to erase elements from an array. The size of an array cannot change. So to be clear, we are considering algorithm where the resulting array contains the elements excluding the "removed" value at the beginning of the array, with some irrelevant value in the end.

The algorithm that you show 1 is the optimal one if there is an additional constraint that the order of other elements must not change. It can be slightly improved by using move assignment if the element type is non-trivial, but that doesn't improve asymptotic complexity. There is no need to write the loop, since there is a standard algorithm: std::move (the two-argument overload from <algorithm> ).

If there is no constraint of stable order, then there is a more efficient algorithm: Only write the last element over the "removed" one.

is random removal [from array] necessarily always O(n)?

Only when the remaining elements need to have a stable order.


1 However, there is a bug in your implementation:

 for(int i = 6; i < n; ++i) array[i] = array[i+1];

Where n is the size of the array

If n is the size of the array, then array[n-1+1] is outside the bounds of the array.

There are a few more options you can consider.

  1. Validity masks

You can have an additional array of bool initially everything is set to false to day values are not deleted. To delete the value you set the corresponding bool to true (or the other way if it makes more sense in your code).

This requires a bit of tweaks to the rest of the code to skip values that are marked as deleted.

  1. Tombstones

Similar to the solution above, but doesn't require additional memory. If there's a value that it's not used (say all the values are supposed to be positive, then we can use -1) you can set the entry to that value. This also requires tweaks in the rest of the code to skip it.

  1. Delayed deletion

This one is a bit more complicated. I'd only use it if iterating over the deleted entries significantly affects performance or complexity.

The idea is to tombsone or mark the entries as deleted. Next time you iterate over the array you also do the swaps. This makes the code kind of complex. The easiest, I think, you can do it is using custom iterators. This is still O(N), but it's amortized O(1) within the overall algorithm.

Also note that if you do a loop O(N) to find the element to delete and than do another loop O(N) to delete it, then the overall solution is still O(N).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM