题目
给定一个非空列表 nums,请将 nums 中所有 0 移动到列表的末尾,同时保持非零元素的相对顺序。
注意:只允许在原列表nums上操作,而不能返回一个新创建的列表。
例如:
给定一个列表:[0, 1, 0, 3, 12],返回结果:[1, 3, 12, 0, 0]
实现思路1
- 使用类似冒泡排序的方式(每次把较大的值交换移到后面),而这里是每次把 0 移动到最后,但整个过程需要 2 层遍历
- 第一层遍历控制需要几轮,同时设置一个交换标记flag,默认为True
- 第二层遍历控制每次比较元素下标,如果发现当前元素为 0 ,且下一个元素不为 0 ,那么就把二者顺序交换,并把flag置为False
- 每轮循环都能够把一个 0 移动到列表末尾,直到发现某次循环中,列表已经是排序好的,没有进行任何元素交换(flag=True),那么就可以直接break退出,并返回列表
代码实现
def moveZeroes(nums):
for i in range(len(nums)):
flag = True
for j in range(len(nums) - i - 1):
if nums[j] == 0 and nums[j + 1] != 0:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
flag = False
if flag:
break
return nums
实现思路2
- 设置一个index,表示列表的下标,默认值为 0
- 遍历nums,如果当前元素不为 0 ,那么就把列表nums中 index 下标对应的元素设置为当前元素,同时令 index + 1,这样遍历完成后,前 index 个元素必然就是原列表 nums 中的所有非零元素
- 再次遍历,起始位置为 index ,结束位置为 len(nums) ,每次都把列表 nums 中当前位置的元素设置为 0 ,最后得到的 nums 即为移动零后的结果
代码实现
def moveZeroes(nums):
index = 0
for num in nums:
if num != 0:
nums[index] = num
index += 1
for i in range(index, len(nums)):
nums[i] = 0
return nums
实现思路3
- 设置2个变量 left 和 right ,left表示指向列表中非零元素的下标,right表示指向列表的下标
- 通过 while循环 来实现,只要满足 right < len(nums) 都会进行循环
- 如果当前元素 nums[right] 为 0 ,则 left 保持不变
- 如果当前元素 nums[right] 不为 0,且同时满足 left != right,那么就需要交换 left 和 right 对应的元素,即把当前的非 0 元素移到前面去。但不管是否交换元素,最后 left 都需要向右移动,即 left + 1
- 不管当前元素 nums[right] 是否为0,每次遍历最后 right 都需要向右移动 ,即right + 1
使用上面方法,可以发现有以下特点:
- left左侧的所有元素,都将是非 0 元素
- 从left右侧到right左侧的所有元素,都将是 0 元素
每次交换都是 left 当前对应的 0 元素与 right 对应的非 0 元素进行交换,所以最终得到的 nums 中,非零元素的相对顺序是保持不变的。
代码实现
def moveZeroes(nums):
left = right = 0
while right < len(nums):
if nums[right] != 0:
if left != right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right += 1
return nums