Reputation: 541
So the goal here is to move all 0's to the end of the array but I stumble across a problem from these small lines of code.
When I use the input I get the desired output like so:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
However, whenever I use this input:
[0,0,1]
I get this output:
[0,1,0]
When I want the output:
[1,0,0]
I have no idea why I thought I implemented this properly:
class Solution:
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
for counter in range(len(nums)):
if nums[counter] == 0:
nums.pop(counter) #Remove the 0
nums.append(0) #Add to end.
counter-=1 #Check same index just incase adjacent 0
Any input is appreciated. Thanks!
Upvotes: 2
Views: 123
Reputation: 31339
This line:
counter-=1 #Check same index just incase adjacent 0
Does not decrease the indexing for the following indices.
Try this instead:
class Solution:
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
zeros_found = 0
for counter in range(len(nums)):
idx = counter - zeros_found
if nums[idx] == 0:
nums.pop(idx) #Remove the 0
nums.append(0) #Add to end.
zeros_found += 1 #Account for offset
You could also do this more functionally:
from itertools import filterfalse
# ...
def moveZeroes(self, nums):
none_zeroes = list(filter(None, nums))
zeros = list(filterfalse(None, nums))
return none_zeros + zeros
Or if you don't want to create lists for no reason:
from itertools import filterfalse, chain
# ...
def moveZeroes(self, nums):
none_zeroes = filter(None, nums)
zeros = filterfalse(None, nums)
return list(chain(none_zeros, zeros))
These rely on two implicit facts:
bool(0)
is False
, and bool(x)
when x != 0
is True
filter(None, list)
filters list by item's bool
value, so no 0s (and opposite for filterfalse)Upvotes: 3
Reputation: 15071
A for
loop is not a equivalent to a while
loop with increment. Your last line counter-=1
doesn't achieve anything: after you decrement counter
, it immediately takes the next value in the range. (To be clear, if you were at iteration counter = 2
for example, no matter what value you leave counter
at at the end of this iteration, it will be reassigned to 3
at the next iteration.)
Upvotes: 4
Reputation: 168913
I wouldn't even bother with a manual for loop...
def move_zeroes(nums):
nums[:] = [n for n in nums if n != 0] + [0] * nums.count(0)
x = [0,1,0,3,12]
move_zeroes(x)
print(x)
outputs
[1, 3, 12, 0, 0]
Upvotes: 5