1 题目
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = 0,1,0,3,12
输出: 1,3,12,0,0
示例 2:
输入: nums = 0
输出: 0
2 分析
要想把0移动到数组末尾,直觉是从左往右看,每遇到一个0,就将它与右边第一个非零元素交换,但这个方式很乱,时间复杂度很高:
- 首先会导致同一个非零元素被多次交换(如果其左边有很多个0)
- 需要同时维护当前0的位置,和右边第一个非0的位置,相当于外面一层O(n)遍历,里面还有一层O(n)遍历
要想全程只用一遍遍历,并且保持非零元素的相对顺序,还有一种方法是用一个数组把从左到右遇到的非零元素都记录下来,然后在末尾填补遇到的0,但这不符合题目要求的在原地对数组进行操作。
但从记录非零元素的角度出发,双指针同样可以完成,左指针left记录index,右指针right记录待放入的元素。类似ansi=num的新数组赋值操作,双指针只能通过元素交换来完成,即numleft, numsright=numsright, numsleft。当left=right=0时,如果numright=0,right需要右移直到非零,然后交换;如果numright>0,那么left和right的元素交换(相当于没交换),然后left和right都右移。因此,left的位置要么跟right在一起,要么停在零元素上,所以双指针元素交换能够实现用新数据记录非零元素一样的效果。
3 代码
python
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
l, r = 0,0
while r < n:
if nums[r] != 0:
nums[l], nums[r] = nums[r], nums[l]
l += 1
r += 1