已解答
简单
相关标签
相关企业
提示
给定一个数组 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
进阶:你能尽量减少完成的操作次数吗?
超时代码
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
for m in range(len(nums)):
for i in range(0,len(nums)-1):
if nums[i] == 0:
for j in range(i,len(nums)-1):
case = nums[j+1]
nums[j+1] = nums[j]
nums[j]=case
return nums
冗余的嵌套循环:
- 该代码在每次遇到
0
时,都会从当前位置将后面的元素逐个交换。由于moveZeroes
的任务仅仅是将所有非零元素前移,零元素移动到末尾,过多的循环和交换操作会降低效率。算法效率低:
- 当前算法的时间复杂度是 O(n3)O(n^3)O(n3)(三个嵌套循环),会在数据量大时显著拖慢程序的执行速度。优化可以通过在一个循环中完成。
一种改进方案是使用 双指针法,将时间复杂度降至 O(n)O(n)O(n)。以下是优化后的代码
from typing import List
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
# 指针 j 记录非零元素的放置位置
j = 0
for i in range(len(nums)):
# 如果 nums[i] 非零,则将其放在 j 指针的位置,j 向后移
if nums[i] != 0:
nums[j] = nums[i]
j += 1
# 将剩余的位置填充为 0
for i in range(j, len(nums)):
nums[i] = 0
优化后的代码说明
- 第一个循环遍历数组,将非零元素按顺序移到数组的前部分,同时
j
指针记录下一个放置非零元素的位置。- 第二个循环从
j
开始,将剩余位置全部设置为0
,确保所有0
都移到末尾。- 时间复杂度为 O(n)O(n)O(n),因为只需遍历数组一次,并在需要时移动非零元素或填充零。
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
# 获取数组的长度
n = len(nums)
# 初始化两个指针,left和right,分别指向非零元素的插入位置和当前遍历的位置
left = right = 0
# 使用while循环遍历数组
while right < n:
# 如果当前遍历到的元素不是0
if nums[right] != 0:
# 将非零元素与left指针指向的位置的元素交换
nums[left], nums[right] = nums[right], nums[left]
# 移动left指针到下一个位置,为下一个非零元素做准备
left += 1
# 无论当前元素是否为0,都移动right指针到下一个位置
right += 1