Although the problem is described in terms of separate steps (modify array, reorder it), we don't actually have to perform exactly those steps, provided we print the correct result.
A more efficient way to process the array is to maintain an input pointer and an output pointer (or indexes - the logic is equivalent), and a simple count of the trailing zeros (which we can just compute, as the output array must be the same length as the input array).
Then, for each element in the input array:
- if it's zero, skip it (and don't advance the output pointer)
- if differs from the the following element, copy it to output unchanged
- else double it and copy to the output, then skip the next input value
When you reach the end of the array, fill the remainder of the output with zeros.
It's quite reasonable to re-use the input array as the output, as you'll never overwrite a value you'll subsequently need. In fact, since the algorithm is single-pass, we don't need to store the input in an array at all.
You don't actually need to write zeros to the output array, as you only need to print the right results: if you have n non-zero values in the output array, then print those values, followed by N-n zeros.