In the comments, you presented almost all possible ways to solve the problem.
Of course, the classic pattern for solving this is two pointers.
Here is the ideal solution with
O(n) time complexity and O(1) memory:def move_zeroes(nums: list[int]) -> None:
insert_pos = 0
for i in range(len(nums)):
if nums[i] != 0:
# Swap non-zero element with the "leftmost" zero
nums[insert_pos], nums[i] = nums[i], nums[insert_pos]
insert_pos += 1No allocations. No
pop() from the middle of the list. We traverse the array exactly once. The variable insert_pos always points to the first available zero. As soon as we find a number different from zero, we simply swap them thanks to Python's built-in tuple unpacking mechanism.🐍 But it wouldn't be interesting without something trickier. Here's a Pythonic one-liner without generators:
nums.sort(key=bool, reverse=True)How does it work?
bool(0) gives False, other numbers give True. Python's built-in Timsort is stable — it strictly preserves the original order of equal elements. All True (numbers) will move to the left, preserving their order, and all False (zeros) will fly to the right.Yes, formally this has O(n log n) complexity, which is algorithmically worse than two pointers. But because Timsort is written in blistering C, on real small lists this code will physically outperform pure Python loops in execution speed.
#algosobes
Comments
0No comments yet.