Do not keep erasing from the vector. Instead, use the read-write-pointer pattern. It performs much better and is easier to reason about.
template <typename T>
void removeUnsorted(std::vector<T>& vec) {
if (vec.empty()) return;
auto last = begin(vec);
auto write = begin(vec);
for (auto read = begin(vec); read != end(vec); ++read) {
if (!(*last < *read)) {
*write++ = *read;
}
last = read; // !
}
vec.resize(distance(begin(vec),write));
}
Basically this tracks all value you want to keep between begin(vec)
and write
. The read
iterator goes over every value once and copies it to *write
if and only if you decide to keep it.
You can decide with which value to compare, the last one read or the last one written. The code as it stands now compares against the last one read, such that this:
{7,6,9,4,3,8,5,2}
gets transformed to this:
{7,6,4,3,5,2}
^----- note the 5
If you do not want this, but want to always have a descending value, move the line with a // !
comment inside the if condition, thereby only updating the "compare-to" value when it was kept, not when it was encountered.
In the very last line, you truncate the vector, dropping every value that was not kept. Note that this is done in constant time for integers.