I had an interview for a Jr. development job and he asked me to write a procedure that takes an array of ints and shoves the zeroes to the back. Here are the constraints (wh
This is O(n) so it may be what he's looking for:
auto arrBegin = begin(arr);
const auto arrEnd = end(arr);
for(int i = 0; arrBegin < arrEnd - i; ++arrBegin){
if(*arrBegin == 0){
i++;
*arrBegin = *(arrEnd - i);
}
}
std::fill(arrBegin, arrEnd, 0);
Maybe the interviewer was looking for this answer:
#include <algorithm>
//...
std::partition(std::begin(arr), std::end(arr), [](int n) { return n != 0; });
If the order needs to be preserved, then std::stable_partition
should be used:
#include <algorithm>
//...
std::stable_partition(std::begin(arr), std::end(arr), [](int n) { return n != 0; });
For pre C++11:
#include <functional>
#include <algorithm>
//...
std::partition(arr, arr + sizeof(arr)/sizeof(int),
std::bind1st(std::not_equal_to<int>(), 0));
Live Example
Basically, if the situation is that you need to move items that satisfy a condition to "one side" of a container, then the partition algorithm functions should be high up on the list of solutions to choose (if not the solution to use).
An approach that sorts is O(N*Log2N). There is a linear solution that goes like this:
readPtr
and writePtr
, initially pointing to the beginning of the arrayreadPtr
up the array to the end. If *readPtr
is not zero, copy to *writePtr
, and advance both pointers; otherwise, advance only readPtr
.readPtr
is at the end of the array, walk writePtr
to the end of the array, while writing zeros to the remaining elements.