Move Zeroes

Question (LC.283)

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.

Example

Input: nums = [0, 1, 0, 3, 12]
Output: nums = [1, 3, 12, 0, 0]

Super Brute Force Approach

Just create a new array. Then copy over the non-zero elements in order and done.

def moveZeroes(self, nums: List[int]) -> List[int]:
    n = len(nums)
    if n == 0:
        return
    
    copy_array = [0 for i in range(n)]
    
    non_zero_index = 0
    for ele in nums:
        if ele != 0:
            copy_array[non_zero_index] = ele
            non_zero_index += 1

    return copy_array

The time complexity is O(n)O(n). The space complexity is also O(n)O(n).

Brute Force Approach

Brute Force Code

Version1: Swapping zeroes to the end

Version 2: Swapping non-zero elements to the front

Slower with O(n2)O(n^2) time but in place

Better Approach

Store a count for zero shift every up then pad zeroes. The tricky park is how to count and shift.

Code

Alternative Approach

We can do something similar to first approach but have to swap. Swap after the last non-zero element with a single scan.

O(n)O(n) time with O(1)O(1) space

Proof sketch

Assume there is a dummy non-zero element before the list. Every element has 2 cases, zero or non-zero. For zero, we can simply ignore them. For non-zero, if it gets swapped right after the previous non-zero element, then the relative ordering is kept and there is no zeroes between the non-zero elements. Non-zero element will never get swapped with another non-zero element because if a non-zero element appears right after another non-zero element then it will just swap with itself. If a non-zero element does not appear right after another non-zero element, then that means there must be some zeroes between them and swapping with zeroes is fine in that sense that we don't have to keep a relative ordering of the zeroes.

Last updated