数组移零功能:JavaScript实现代码在特定测试用例下的异常问题
数组移零代码的问题分析与修复
问题现象
原代码在处理[0,0,1]这类包含连续0的数组时,返回结果为[0,1,0],不符合将所有0移到末尾的要求,但处理[0,1,0,3,12]这类非连续0的数组时能正常运行。
问题原因
原代码通过for循环从前往后遍历数组,遇到0时执行splice(i,1)删除当前元素,再用push(0)把0放到数组末尾。但splice会直接修改数组结构:删除元素后,后续元素会向前移位填补空缺,而循环的i会继续自增,导致跳过了移位到当前i位置的新元素。
以[0,0,1]为例:
- 第一次循环
i=0,删除索引0的0,数组变为[0,1],push 0后变成[0,1,0]; - 循环
i自增到1,此时nums[1]是1,不触发处理; - 循环
i自增到2,nums[2]是0,删除后数组变为[0,1],push 0后回到[0,1,0],循环结束。
整个过程中,原本索引1的0被跳过,没有被移到末尾。
修复方案
方案一:调整索引避免跳过元素
当删除元素后,让i自减一次,抵消循环的自增操作,确保下一次循环能检查到移位过来的元素:
var moveZeroes = function(nums) { for (let i = 0; i < nums.length; i++) { if (nums[i] === 0) { nums.splice(i, 1); nums.push(0); i--; // 回退索引,避免跳过移位后的元素 } } return nums; };
方案二:双指针法(更高效)
避免频繁使用splice(数组删除操作时间复杂度较高),用快慢指针分离非零元素和零元素,最后统一填充0:
var moveZeroes = function(nums) { let slow = 0; // 将所有非零元素移到数组前半部分 for (let fast = 0; fast < nums.length; fast++) { if (nums[fast] !== 0) { nums[slow] = nums[fast]; slow++; } } // 从slow位置开始,将剩余位置填充为0 for (let i = slow; i < nums.length; i++) { nums[i] = 0; } return nums; };
该方法时间复杂度为O(n),空间复杂度为O(1),在处理大数组时性能更优。
内容的提问来源于stack exchange,提问作者coderobsessed
相关产品推荐
相关产品推荐

