描述
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
示例 2:
输入: nums =[0]
输出:[0]
提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
进阶:你能尽量减少完成的操作次数吗?
分析
不复制数组:不可以开辟新空间,即不能自定义其他数组(若是无这个条件,可以将非零与零分别放入两个数组,再用( [非零].extend([零] )
简洁代码
直接使用python的内置函数remove(0),append(0),一个移除并拼接到末尾即可实现
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
for i in range(len(nums)):
if nums[i]==0:
nums.remove(0)
nums.append(0)
转自leecode题解Shawxing精讲算法
本篇统一采用如下数组,并且采用双指针。蓝色指针为 l,橙色指针为 r。初始 l,r 的 index 均为 0。
解法一
记元素向左的偏移量为 offset,初始 offset = 0。
每次发现元素为 0 时增加偏移量,发现元素非 0 且偏移量非 0 时偏移元素。
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
offset = 0 # 初始化偏移量为0,用于记录遇到的0的个数
for i in range(len(nums)): # 遍历整个数组
if nums[i] == 0: # 如果当前元素是0
offset += 1 # 将偏移量加1
elif offset != 0: # 如果当前元素不是0且偏移量不为0
nums[i - offset] = nums[i] # 将当前元素移动到前面偏移量的位置
nums[i] = 0 # 将当前元素位置设为0
解法二
如下所示,我们可以将 l 移动到自身右侧第一个元素为 0 的位置,将 r 移动到 l 右侧第一个元素非 0 的位置,然后交换元素。
然后再执行上一步骤,循环下去,直至r 抵达边界。
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
l = 0 # 初始化左指针 l 为 0
r = 0 # 初始化右指针 r 为 0
while r < len(nums): # 当右指针 r 小于数组长度时,进行循环
if r == l or nums[r] == 0: # 如果右指针和左指针相等,或者右指针指向的元素为0
r += 1 # 右指针向右移动一位
elif nums[l] != 0: # 如果左指针指向的元素不为0
l += 1 # 左指针向右移动一位
else: # 如果左指针指向的元素为0且右指针指向的元素不为0
nums[l] = nums[r] # 将右指针指向的元素赋值给左指针指向的位置
nums[r] = 0 # 将右指针指向的位置设为0
解法三
出发点是记录第一个元素为 0 的位置,并在每次交换元素时更新。
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
l = 0 # 初始化左指针 l 为 0
for r in range(len(nums)): # 遍历整个数组,右指针 r 从 0 到 len(nums) - 1
if nums[r] == 0: # 如果当前元素为 0,则跳过
continue
nums[l], nums[r] = nums[r], nums[l] # 交换左指针 l 和右指针 r 指向的元素
l += 1 # 左指针 l 右移一位
取示例数组如下所示,分析代码的运行过程。
初始时 Nums[l]=Nums[r] != 0,交换不产生影响。l,r 同步前进。
如下所示,在发现元素 0 时,l 保持不变,r 前进至 Nums[r] != 0。
再如下所示,交换元素,l 前进。
此后 r 前进,一直寻找非 0 元素与 l 处的 0 交换即可。
复杂度
以上解法复杂度一致。
时间:Θ(n)
空间:Θ(1)