Move All Zeros to the End of an Array

medium

By - Aman Pareek

Last Updated - 27/08/2024

Problem Statement

Write a JavaScript function that moves all zeroes in an array to the end while maintaining the order of non-zero elements. The function should also handle input validation.

Example 1

Input: array = [0, 1, 0, 3, 12]

Output: [1, 3, 12, 0, 0]

Example 2

Input: num = 4

Output: Throw error => Input must be an array

Solution 1: Using Two-Pointer Technique

function moveZerosToEndTwoPointer(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let nonZeroIndex = 0;
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] !== 0) {
            [arr[nonZeroIndex], arr[i]] = [arr[i], arr[nonZeroIndex]];
            nonZeroIndex++;
        }
    }
    return arr;
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndTwoPointer(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndTwoPointer(num2);  //Throw error => Input must be an array 

Solution 2: Using filter() and concat()

function moveZerosToEndFilterConcat(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let nonZeros = arr.filter(num => num !== 0);
    let zeros = arr.filter(num => num === 0);
    return nonZeros.concat(zeros);
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndFilterConcat(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndFilterConcat(num2);  //Throw error => Input must be an array 

Solution 3: Using reduce()

function moveZerosToEndReduce(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    return arr.reduce((acc, num) => {
        if (num !== 0) acc.push(num);
        return acc;
    }, []).concat(arr.filter(num => num === 0));
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndReduce(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndReduce(num2);  //Throw error => Input must be an array 

Solution 4: Using for Loop

function moveZerosToEndForLoop(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let result = [];
    let zeroCount = 0;
    for (let num of arr) {
        if (num === 0) {
            zeroCount++;
        } else {
            result.push(num);
        }
    }
    while (zeroCount-- > 0) {
        result.push(0);
    }
    return result;
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndForLoop(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndForLoop(num2);  //Throw error => Input must be an array 

Solution 5: Using map() and filter()

function moveZerosToEndMapFilter(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    return arr.map(num => num === 0 ? null : num)
              .filter(num => num !== null)
              .concat(arr.filter(num => num === 0));
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndMapFilter(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndMapFilter(num2);  //Throw error => Input must be an array 

Solution 6: Using copyWithin() Method

function moveZerosToEndCopyWithin(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let writeIndex = 0;
    for (let readIndex = 0; readIndex < arr.length; readIndex++) {
        if (arr[readIndex] !== 0) {
            arr[writeIndex++] = arr[readIndex];
        }
    }
    for (let i = writeIndex; i < arr.length; i++) {
        arr[i] = 0;
    }
    return arr;
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndCopyWithin(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndCopyWithin(num2);  //Throw error => Input must be an array 

Solution 7: Using fill() Method

function moveZerosToEndFill(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let zeroCount = arr.filter(num => num === 0).length;
    let result = arr.filter(num => num !== 0);
    result.length = arr.length;
    result.fill(0, result.length - zeroCount);
    return result;
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndFill(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndFill(num2);  //Throw error => Input must be an array 

Solution 8: Using splice() Method

function moveZerosToEndSplice(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let zeroCount = 0;
    for (let i = arr.length - 1; i >= 0; i--) {
        if (arr[i] === 0) {
            arr.splice(i, 1);
            zeroCount++;
        }
    }
    arr.length = arr.length + zeroCount;
    arr.fill(0, arr.length - zeroCount);
    return arr;
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndSplice(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndSplice(num2);  //Throw error => Input must be an array 

Solution 9: Using Array.from()

function moveZerosToEndArrayFrom(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let nonZeros = arr.filter(num => num !== 0);
    let zeros = arr.length - nonZeros.length;
    return Array.from(nonZeros).concat(Array(zeros).fill(0));
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndArrayFrom(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndArrayFrom(num2);  //Throw error => Input must be an array 

Solution 10: Using Set and Array

function moveZerosToEndSetArray(arr) {
    if (!Array.isArray(arr)) {
        throw new TypeError('Input must be an array');
    }
    let nonZeros = [...new Set(arr.filter(num => num !== 0))];
    let zeroCount = arr.length - nonZeros.length;
    return nonZeros.concat(Array(zeroCount).fill(0));
} 

const array1 = [0, 1, 0, 3, 12];
moveZerosToEndSetArray(array1);  //output: [1, 3, 12, 0, 0] 

const num2 = 4;
moveZerosToEndSetArray(num2);  //Throw error => Input must be an array