The into_iter + filter + collect approach won't clone the items (they are simply moved to the new vector), but collect will allocate a new buffer for the output vector, and the old vector's buffer will be deallocated. retain won't allocate.
Is the filter + collect method actually linear time? Because Filter does not implement ExactSizeIterator so I guess that collect cannot preallocate the necessary amount of memory which in turn means that the whole operation would be in O(n log n), no?
I suppose it would work with a pre-allocated vector of at least the same size as the original, as a slightly different angle to the iterator solution. Then you should be able to use empty_vec.extend(filtered_iterator);. Rust Playground
But you might as well use retain, as suggested above, and spare yourself that extra allocation, if you don't need to or want to also change the type of the content.