给定一个数组 nums
,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意,必须在不复制数组的情况下原地对数组进行操作。
nums = [0,1,0,3,12]
[1,3,12,0,0]
nums = [0]
[0]
根据题意,如果要在在不复制数组的情况下解决这个问题,==> 需要一个满足O(1)空间复杂度的算法,并且适合解决数组/列表数据结构的问题 ==> 自然想到双指针算法。
双指针法是一种常用的算法思想,用于解决数组和链表等数据结构的问题。它的基本思想是使用两个指针(不一定真是指针,能存储相应元素的位置/索引就行)分别标记两个位置/索引,然后通过指针所指元素的性质对数组进行修改,同时指针进行移动完成目标的方法。
我们可以定义两个指针left
和right
,其中:
left
:标记当前非零元素应该放置的位置right
:标记当前遍历到的位置。当我们通过右指针的移动遍历数组元素时,
left
位置的元素交换,并将left
和right
都向后移动一位。
left
向后移动一位的原因:更新下一个非零元素应该放置的位置;right
向后移动一位的原因:遍历下一个数组元素;right
—> 遍历下一个数组元素;left
—> 当前位置仍然是下一个非零元素应该放置的位置;当循环结束后,所有非零元素都会被移动到数组的前面,而所有0元素则会被移动到数组的末尾。
对左指针left
和右指针right
的具体功能有明确的认知,可以更好地帮助我们理解算法的运行逻辑。
from typing import List
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
将数组中的所有零移动到数组的末尾,保持非零元素的相对顺序。
Args:
nums (List[int]): 待操作的数组。
Returns:
None: 该函数没有返回值,直接修改传入的数组。
"""
n = len(nums)
# left和right分别表示当前非零元素应该放置的位置和当前遍历到的位置。
left = 0 # left初始化为0,表示第一个位置是非零元素应该放置的位置。
right = 0 # right初始化为0,表示开始从数组的第一个位置遍历。
# 通过右指针的移动遍历数组
while right < n:
# 如果当前遍历到的元素不为0,则将其与left位置的元素交换,并将left和right都向后移动一位。
if nums[right] != 0:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right += 1
nums
元素的数量。