Python列表移零逻辑异常:输入[0,0,1]无法得到正确输出
问题分析与解决思路
咱们先拆解下你这段代码的问题所在:
你的核心思路是遍历数组,遇到0就把它移到末尾,这个方向是对的,但for循环的遍历逻辑和数组修改的冲突导致了错误:
- 你用
for counter in range(len(nums))遍历,range生成的是固定的序列(比如输入[0,0,1]时,range(3)就是0、1、2),不管你在循环里怎么修改数组长度,循环的counter都会按这个固定序列走。 - 你手动写的
counter -=1完全没用,因为for循环每次迭代都会从range里取下一个值,直接覆盖你修改的counter。
举个[0,0,1]的执行流程就能看明白:
- 第一次循环counter=0,nums[0]是0,pop后数组变成
[0,1],append0后变成[0,1,0],你把counter改成-1,但下一次循环counter直接跳到1。 - 此时nums[1]是1,不触发操作,循环直接结束,结果就变成了
[0,1,0],不符合预期。
解决思路1:倒序遍历数组
最简单的修正方式就是倒着遍历数组,这样就算你pop元素,前面还没处理的元素索引不会受到影响(因为我们从后往前处理,移除后面的元素不会改变前面元素的位置)。
修正后的代码:
class Solution: def moveZeroes(self, nums): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ # 从最后一个元素往前遍历 for counter in range(len(nums)-1, -1, -1): if nums[counter] == 0: nums.pop(counter) nums.append(0)
拿[0,0,1]测试下:
- counter=2:元素是1,跳过;
- counter=1:元素是0,pop后数组变成
[0,1],append0后变成[0,1,0]; - counter=0:元素是0,pop后数组变成
[1,0],append0后变成[1,0,0],完美得到预期结果。
解决思路2:双指针法(更高效)
上面的方法虽然简单,但频繁的pop操作(尤其是在数组开头pop)时间复杂度是O(n),如果数组很大,效率会很低。推荐用双指针法,只需要遍历数组两次,完全避免删除/添加操作,时间复杂度O(n),空间复杂度O(1)。
实现逻辑:
- 用一个慢指针
non_zero_idx标记下一个非0元素应该放置的位置; - 快指针遍历整个数组,遇到非0元素就和慢指针位置的元素交换,慢指针右移;
- 遍历结束后,慢指针后面的所有位置统一填0。
代码如下:
class Solution: def moveZeroes(self, nums): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ non_zero_idx = 0 # 把所有非0元素移到数组前面 for i in range(len(nums)): if nums[i] != 0: nums[non_zero_idx], nums[i] = nums[i], nums[non_zero_idx] non_zero_idx += 1 # 把慢指针后面的位置全部设为0 for i in range(non_zero_idx, len(nums)): nums[i] = 0
这个方法不仅能正确处理[0,0,1]这种情况,对于大规模数组的处理效率也高很多,是这类问题的最优解法之一。
内容的提问来源于stack exchange,提问作者Michael Gee
相关产品推荐
相关产品推荐

