283. 移动零
题目
-
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
python
法一、暴力法
- 遍历找到零元素,并暂时保存,然后在零元素往后的都前移一位,最后在给最后一位赋给暂存的值
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
for i in range(n):
if nums[i] == 0:
for j in range(i+1,n):
nums[j-1] = nums[j]
j += 1
nums[n-1] = 0
i +=1
- 错误:当测试用例刚好有两个挨着的0元素时就会报错。

- 原因:当遇到第一个0元素时,0元素后面的依次往前一位,最后一位补0,然后进行i+1进行判断,此时,第二个0元素补在了第一个0元素原来的位置,i+1直接跳过了第二个0元素的判断,导致出错。
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
i = 0
while i < n:
if nums[i] == 0:
for j in range(i+1, n):
nums[j-1] = nums[j]
nums[n-1] = 0
if nums[i] != 0 and i > 0:
i += 1
else:
i = i
if i < 0: # 处理i小于0的情况
i = 0
else:
i += 1
- 超出时间限制

- 该方法没有成功解决问题(条件判断存在逻辑矛盾),欢迎大家多多指教
法二、双指针
class Solution:
def moveZeroes(self, nums):
i = 0
j = 0
n = len(nums)
for i in range(n):#把数组中不是0元素的往前移
nums[j] = nums[i]
if nums[i] != 0:#当元素不为0时j才往后移一位,,是0时不动等着nums[j] = nums[i]不为0的替代
j += 1 #j最终停在最后一个不为0的元素
while j < n:#剩余的位置全部补0
nums[j] = 0
j += 1
法三、pop+append
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
n = len(nums)
i = 0
while i < n:
if nums[i] == 0:
nums.pop(i)#将其从数组中移除
nums.append(0)#将零追加到数组的末尾
n -= 1#.pop(i) 将零元素从数组中移除,导致数组的长度减少了1。为了确保循环在正确的范围内进行迭代,需要相应地更新 n 的值。
else:#如果当前元素不是零
i += 1#则将索引 i 的值增加 1,以继续下一轮迭代
JavaScript
法一:暴力--存在很大问题
- 遍历遇到0就把后面的元素往前覆盖,在末尾push(0)
- 问题:无法处理连续的零的情况,push会改变数组长度,影响索引。
var moveZeroes = function(nums) {
//遍历遇到0就把后面的元素往前覆盖,在末尾push(0)
//问题:往前覆盖的时候数组长度会缩短
for(let i=0;i<nums.length;i++){
if(nums[i]==0){
nums.push(0)
for(let j=i;j<nums.length-1;j++){//范围也有问题,nums.length-1保证nums[j+1]不超出,但是会少一位数组元素
nums[j]=nums[j+1]
}
i=i-1//i为0时减1为负数
}
}
return nums
}
法二:filter过滤0---会改变原数组
- 思路:使用filter过滤0,根据过滤前后的数组长度差确定在数组后push多少个0
- 问题:首先,使用 filter 方法会创建一个新的数组并赋值给 nums,这会导致原数组的引用丢失。可以把过滤后的数组赋给一个新数组操作,但是不符合题意不是对原数组进行操作
var moveZeroes = function(nums) {
//使用filter
//问题:使用 filter 方法会创建一个新的数组并赋值给 nums,这会导致原数组的引用丢失。
//接下来对 nums 的所有操作都在新的数组上进行,而不是原始数组。
let l1=nums.length
nums=nums.filter(function(item){
return item !==0
})
let l2=nums.length
let cnt=l1-l2
while(cnt!=0){
nums.push(0)
cnt--
}
return nums
};
法三:双指针冒泡排序思想
var moveZeroes = function(nums) {
//双指针冒泡
for(let i=0;i<nums.length;i++){
for(let j=i;j<nums.length;j++){
if(nums[i]==0){//如果当前值为0就与后一个值交换
let t=nums[i]
nums[i]=nums[j]
nums[j]=t
}
}
}
return nums
};
法四:双指针
- 思路:一个指针从头开始用来确定不为0的元素放置的位置,另一个指针用来找到不为0的数,将不为0的数放到第一个指针的位置。第二个指针遍历到尾时结束,第一个指针后面到数组末尾全部添加0。
var moveZeroes = function(nums) {
let a=0//指针一确定非0元素放置的位置
for(let i=0;i<nums.length;i++){
if(nums[i]!==0){//找到非0元素
nums[a]=nums[i]//赋值给指针一对应的位置
a++
}
}
for(let i=a;i<nums.length;i++){
nums[i]=0
}
return nums
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人