483 字
2 分钟
移动零

题目描述
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
解题思路
- 双指针策略:
- 使用快慢指针:快指针遍历数组,慢指针标记非零元素位置
- 快指针遇到非零元素时,与慢指针交换位置
- 慢指针仅在前移后更新位置
- 原位操作:
- 所有操作在输入数组上完成
- 不创建新数组,减少空间占用
- 顺序保持:
- 非零元素交换后保留原始顺序
- 零元素自然被推向数组末端
- 优化交换:
- 避免同位置元素的无谓交换
- 仅当快慢指针位置不同时执行交换
关键洞察
- 顺序不变性原理:
- 慢指针始终指向首个零位置
- 非零元素按序与前方零交换,保持相对顺序
- 零元素归集:
- 每次交换都将零元素向后移动
- 遍历结束时零自动聚集在尾部
- 边界处理:
- 初始状态慢指针位置正确(首个元素可能是零)
- 数组全零时无需操作
- 高效交换策略:
- 跳过连续非零区域的冗余交换
- 仅当快指针发现非零且慢指针指向零时交换
复杂度分析
指标 | 说明 |
---|---|
时间复杂度 | O(n):单次遍历数组,每个元素处理时间 O(1) |
空间复杂度 | O(1):仅使用两个指针,常数额外空间 |
代码实现
/** * @param {number[]} nums * @return {void} Do not return anything, modify nums in-place instead. */var moveZeroes = function (nums) { let a = 0, b = 0; while (a < nums.length) { if (nums[a] !== 0) { nums[b] = nums[a]; b++; } a++; }
while (b < nums.length) { nums[b++] = 0; }};