I am attempting to complete a leetcode question in JS. I am new to algorithms in general, and am having some trouble getting my first submission accepted.
The question specifies the following:
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.
For example, given nums = [0, 1, 0, 3, 12]
, after calling your function, nums
should be [1, 3, 12, 0, 0]
.
Note: You must do this in-place without making a copy of the array. Minimize the total number of operations.
With that, here is my code:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
var i, temp;
for (i = 0; i < nums.length-1; i++) {
if(nums[i] === 0) {
temp = nums.splice(i, 1);
nums.push(temp[0]);
}
}
return null;
};
The comments at the top of the code sample are provided in their text editor, and led me to believe that I am not supposed to provide any return statement. Though the validator on their site seemed to not want to accept that at all, so I started returning null...
When I log my nums
to the console after handling the input, I am seeing the desired result nums = [1, 3, 12, 0, 0]
. Regardless my answer keeps getting rejected. I would love to understand what I am doing wrong here, so I can fix it.
I understand this may be a duplicate. I saw other responses dealing with C and Java, but none I saw dealt with JS.
I am attempting to complete a leetcode.com question in JS. I am new to algorithms in general, and am having some trouble getting my first submission accepted.
The question specifies the following:
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.
For example, given nums = [0, 1, 0, 3, 12]
, after calling your function, nums
should be [1, 3, 12, 0, 0]
.
Note: You must do this in-place without making a copy of the array. Minimize the total number of operations.
With that, here is my code:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
var i, temp;
for (i = 0; i < nums.length-1; i++) {
if(nums[i] === 0) {
temp = nums.splice(i, 1);
nums.push(temp[0]);
}
}
return null;
};
The comments at the top of the code sample are provided in their text editor, and led me to believe that I am not supposed to provide any return statement. Though the validator on their site seemed to not want to accept that at all, so I started returning null...
When I log my nums
to the console after handling the input, I am seeing the desired result nums = [1, 3, 12, 0, 0]
. Regardless my answer keeps getting rejected. I would love to understand what I am doing wrong here, so I can fix it.
I understand this may be a duplicate. I saw other responses dealing with C and Java, but none I saw dealt with JS.
Share Improve this question edited Oct 26, 2015 at 12:28 Tomáš Zato 53.1k63 gold badges307 silver badges821 bronze badges asked Oct 26, 2015 at 12:14 robabbyrobabby 2,2006 gold badges32 silver badges47 bronze badges 7 | Show 2 more comments24 Answers
Reset to default 14The problem has nothing to do with the return statement, the issue is your algorithm is wrong.
[0,0,1,2,3]
will return [0,1,2,3,0]
When you loop in the positive direction and remove indexes, you skip indexes as the next index slides down to the position you already covered.
You need to loop in the negative direction. Start at the end and go to the start.
for (i = nums.length-1; i>=0; i--) {
This is an O(n) solution to the problem:
var moveZeroes = function (nums) {
let count = 0;
for (let i = 0; i < nums.length; i++) {
if (nums[i] !== 0) {
nums[count++] = nums[i];
}
}
for (let i = count; i < nums.length; i++) {
nums[i] = 0;
}
return nums;
};
As everyone has already stated: when it says do not return anything, simply do not write a return statement.
However, there is a problem with your code. Use the test case [0,0,1]. If you start at the first element so it moves it to the back of the array, [0,1,0]. Now your loop index is looking at the second element which is 1. you've completely missed the second 0.
function myFunction(n) {
// here i have created zeros array to store all zeros.
let zeros = [];
// here i filter out zeros first n array and push them at
// same time to zeros array..
n = n.filter(item => (item !== 0 ? true : zeros.push(item) && false))
// finally i just max the zeros array at end of n array
return n.concat(zeros)
}
If you must provide a return statement, but you are not allowed to return anything, you can just write
return;
Nothing in javascript
null
is not nothing, technically. Try this: typeof null
. You get "object"
, which is pretty much something. If you run a function that really doesn't return anything:
(function(){})();
You will see undefined
in console. So either return undefined
or just return
or nothing at all will be considered OK.
Sorting alternative solution
I just want to propose more practical solution, to give you another point of view. Since it's javascript, you can use sort function. You will have to create your own callback to compare elements though:
array.sort(function(a, b) { ... comparison here ... });
Now in your specific case, what do we want? We state, that
a
is smaller thanb
if and only ifa
is zero andb
is not zero.
So our callback:
function(a, b) {
if(a==0 && b!=0)
return 1;
else if(b==0 && a!=0)
return -1;
else
return 0;
}
Used like this:
var array = [2,6,0,666,-6,142,0,1,-10];
array.sort(function(a, b) {
if(a==0 && b!=0)
return 1;
else if(b==0 && a!=0)
return -1;
else
return 0;
});
This is what we usually do when actually writing a program, because it's easier to understand (once you get used to it), and shorter most of the time.
Try this approach with ES6 Features
let filteredArr = nums.filter((elem) => {
return elem !== 0;
}) // Create a new Array with all non zero elements
let countOfZero = nums.length - filteredArr.length // Get Count of Zero elements
let newArr = [...filteredArr,...Array(countOfZero).fill(0)] // Create a new array containig only zero equivalent to count of zero elements and filtered non zero elements Array
return nums.splice(0,nums.length,...newArr) // Use splice to alter original array and then add new Array using spread operator
This approach can also be used. With two pointers
function shift(arr) {
let i = 0;
let j = arr.length - 1;
while (j > i) {
if (arr[i] === 0) {
// swapping the numbers --->
let last = arr[j];
arr[j] = arr[i];
arr[i] = last;
j--;
} else {
i++;
}
}
return;
}
let arr = [1, 2, 0, 7, 9, 0, 3, 0]
shift(arr)
console.log(arr);
You can iterate each slot, and fill it will a value that comes from another index, one that moves ahead faster when it skips zeroes. The ??
operator can be used when that second index gets out of range:
function moveZeroes(nums) {
for (let i = 0, j = 0; i < nums.length; i++) {
while (nums[j] === 0) j++; // skip zeroes
nums[i] = nums[j++] ?? 0;
}
}
const moveZeros = (arr) => {
const newArray = [];
const allZeros = [];
for(i=0; i < arr.length; i++){
if(arr[i] >= 1){
newArray.push(arr[i]);
}else{
allZeros.push(arr[i])
}
}
return newArray.concat(allZeros);
}
const zeros = moveZeros([1, 3, 5, 0, 7, 0]);
console.log(zeros);
You can try this function:
const shiftIt = array => {
let temp = [...array];
let zeroCounter=0;
for(let i=0;i<array.length;i++){
if(array[i] === 0 ){
array.push(array.splice(i, 1)[0]);
i--
zeroCounter ++
}
if(i+zeroCounter+1 === array.length) break;
}
return array
}
shiftIt([1,0,2,3,0,0,0,4]) // [1,2,3,4,0,0,0,0]
Every time an element of array equals to zero, I send it to the end of array. So all of the other elements shift to left and I have to make i-- . We get stuck at infinity when all zeros go to the right side of the array. We consider the sum of these two conditions as the condition to exit the loop, since we know how many zeros there are and also where we are now is the end point of the non-zero elements.
The shared approach is not suitable for two or more consecutive zeros, below is example:
nums = [0,0,1]
- At index=0 output ==> [0,1,0]
- At index=1 output ==> [0,1,0] Here we are checking index 1 which is nonzero but we miss the 0 at index 0 and result gets messed up.
Here is my approach to resolve the problem:
var moveZeroes = function(nums) {
let len = nums.length
if(len<=1)return nums
let zeroCount=0;
for(let i=0;i<len;i++){
if(nums[i]===0)zeroCount++
else if(nums[i]!=0&&zeroCount!=0){
nums[i-zeroCount]=nums[i]
nums[i]= 0
}
}
};
Sort the array by ascending order than loop from end to beginning to find zeros. When you find it, splice the array which will remove the current index and push zero
var moveZeroes = function(nums) {
nums.sort((a,b) => {return a-b});
for(let index = nums.length - 1; index >= 0 ; index--){
if(nums[index] === 0){
nums.splice(index, 1);
nums.push(0);
}
}
};
// javascript // single array operation:
var a = [1, 2, 0, 0, 3, 0, 3, 0, 2, 0, 0, 0, 5, 0];
function moveZero(b) {
for (var i = b.length - 1; i >= 0; i--) {
if (b[i] === 0) {
b.splice(i, 1);
b.push(0);
}
}
return b;
}
console.log(moveZero(a));
// multiple array operation => another approach // algorithm: push all non zero elements in an array and all zeros in another array // concat them once loop terminates
var a = [1, 2, 0, 0, 3, 0, 3, 0, 2, 0, 0, 0, 5, 0];
var b = [];
var c = [];
function moveZero(data) {
for (var i = 0; i < data.length - 1; i++) {
if (data[i] !== 0) {
b.push(data[i]);
} else {
c.push(0)
}
}
if (c.length > 0) {
b = b.concat(c);
}
return b;
}
console.log(moveZero(a));
It can be done this way too :
var moveZeroes = function(nums) {
var len = nums.length, i = nums.indexOf(0);
while(~i && i < --len){
nums.splice(i, 1);
nums.push(0);
i = nums.indexOf(0);
}
};
Try this one
function order(array){
count = 0;
for(var i=0;i<array.length;i++){
if(array[i] !== 0){
//non zero element count
array[count] = array[i]
count++;
}
}
while(count<array.length){
array[count] = 0
count++
}
return array
}
var array = [1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0]
console.log(order(array))
Here is the simple one
function check(arr){
var i=0;
var j=arr.length-1;
while(j>i+1){
if(arr[i]!==0){
i++;
}
if(arr[j]===0){
j--;
}
if(arr[i]===0){
arr[i]=arr[j];
arr[j]=0;
}
}
return arr;
}
Splice() is used to remove the element (zero in this case). Then, push a zero to the end of the array.
var moveZeroes = function (nums) {
var length = nums.length;
while (length-- > -1) {
if (nums[length] == 0) nums.splice(length, 1).push(0);
}
return nums;
};
function pushZerosToEnd(arr) {
var k=0;
for(let i=0; i<arr.length; i++)
{
if(arr[i] !==0)
{
let temp=arr[i];
arr[i]=arr[k];
arr[k]=temp;
k++;
}
}
return arr;
}
console.log(pushZerosToEnd([0, 1, 2, 0, 3, 0, 5, 6]));
Here is a very simple solution:
Time complexity O(n)
var moveZeroes = function(nums) {
var i = nums.length;
while (i > -1) {
let current = nums[i];
if(nums[i] === 0) {
nums.splice(i,1)
nums.push(current)
}
i--;
}
return nums;
};
let arr = [0,1,0,3,12]
console.log(moveZeroes(arr))
I would give alternate solution. Remove the 0's then add them at the end. Time Complexity: O(n) Space Complexity: O(1)
var moveZeroes = function(nums) {
let countZeros = 0;
for (let i = 0; i < nums.length;)
{
if(nums[i] === 0) //remove zeros and increment the counter
{
nums.splice(i, 1);
countZeros++;
}
else // to deal with input which starts with 0
{
i++;
}
}
for (let j = 0; j < countZeros; j++) //add zeros at the end
{
nums.push(0);
}
return nums;
};
var x = [1,0,0,0,1,0,1];
for(i=x.length-1;i>=0;i--)
x[i]!=0 && x.unshift(x.splice(i,1)[0])
console.log(x);
Try this:
var moveZeroes = function(nums) {
var i;
for (i = 0; i < nums.length; i++) {
if(nums[i] === 0) {
nums = nums.splice(i, 1);
nums.push(0);
}
}
return;
};
Moving Zeros to End of Array with JAVA
import java.util.Arrays;
public class MoveZerosToEndWithJava {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] A = { 6, 8, 0, 2, 3, 0, 4, 1 };
moving(A);
}
public static void moving(int[] a) {
int countZero = 0;
System.out.println(Arrays.toString(a));
System.out.print("[");
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
countZero++;
} else {
if (i + 1 == a.length && countZero == 0) {
System.out.print(a[i] + "]");
} else {
System.out.print(a[i] + ", ");
}
}
}
for (int i = 0; i < countZero; i++) {
if (i + 1 == countZero) {
System.out.print("0");
} else
System.out.print("0, ");
}
if (countZero > 0) {
System.out.println("]");
}
}
}
return null
altogether. – Griffith Commented Oct 26, 2015 at 12:19nums.splice(i,1); nums.push(0)
. – Iggy Commented Nov 7, 2017 at 18:01