2020-11-16 18:13:03 +01:00
|
|
|
from collections import deque
|
2020-11-15 14:51:46 +01:00
|
|
|
|
2020-11-16 18:13:03 +01:00
|
|
|
def move_zeroes_to_end_quadratic(xs):
|
|
|
|
"""
|
|
|
|
This solution is suboptimal. It runs in quadratic time, and it uses constant
|
|
|
|
space.
|
|
|
|
"""
|
2020-11-15 14:51:46 +01:00
|
|
|
i = 0
|
|
|
|
while i < len(xs) - 1:
|
|
|
|
if xs[i] == 0:
|
|
|
|
j = i + 1
|
|
|
|
while j < len(xs) and xs[j] == 0:
|
|
|
|
j += 1
|
|
|
|
if j >= len(xs):
|
|
|
|
break
|
|
|
|
xs[i], xs[j] = xs[j], xs[i]
|
|
|
|
i += 1
|
2020-11-16 18:13:03 +01:00
|
|
|
|
|
|
|
def move_zeroes_to_end_linear(xs):
|
|
|
|
"""
|
|
|
|
This solution is clever. It runs in linear time proportionate to the number
|
|
|
|
of elements in `xs`, and has linear space proportionate to the number of
|
|
|
|
consecutive zeroes in `xs`.
|
|
|
|
"""
|
|
|
|
q = deque()
|
|
|
|
for i in range(len(xs)):
|
|
|
|
if xs[i] == 0:
|
|
|
|
q.append(i)
|
|
|
|
else:
|
|
|
|
if q:
|
|
|
|
j = q.popleft()
|
|
|
|
xs[i], xs[j] = xs[j], xs[i]
|
|
|
|
q.append(i)
|
|
|
|
|
|
|
|
def move_zeroes_to_end_linear_constant_space(xs):
|
|
|
|
"""
|
|
|
|
This is the optimal solution. It runs in linear time and uses constant
|
|
|
|
space.
|
|
|
|
"""
|
|
|
|
i = 0
|
|
|
|
for j in range(len(xs)):
|
|
|
|
if xs[j] != 0:
|
|
|
|
xs[i], xs[j] = xs[j], xs[i]
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
# Tests
|
|
|
|
################################################################################
|
|
|
|
|
|
|
|
xss = [
|
|
|
|
[1, 2, 0, 3, 4, 0, 0, 5, 0],
|
|
|
|
[0, 1, 2, 0, 3, 4],
|
|
|
|
[0, 0],
|
|
|
|
]
|
|
|
|
|
|
|
|
f = move_zeroes_to_end_linear_constant_space
|
|
|
|
|
|
|
|
for xs in xss:
|
|
|
|
print(xs)
|
|
|
|
f(xs)
|
|
|
|
print(xs)
|