You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组移零至末尾算法问题:现有解法不符合预期求解释

数组移零算法问题分析

问题描述

你编写了如下moveZeros函数,意图将数组中所有零移至末尾,同时保留非零元素的原有顺序:

const moveZeros = (arr) => {
  const finalArray = arr;
  finalArray.forEach((element, i) => {
    if (element === 0) {
      finalArray.splice(i, 1);
      finalArray.push(0);
    }
    if (finalArray[i - 1] === 0) {
      finalArray.splice(i - 1, 1);
      finalArray.push(0);
    }
  });
  return finalArray;
};

该函数在调用moveZeros([false,1,0,1,2,0,1,3,"a"])时运行正常,但处理长零数组moveZeros([9, 9, 1, 2, 1, 1, 3, 1, 9, +0, 9, +0, +0, +0, +0, +0, +0, +0, +0, +0])时,结果不符合预期(预期结果为[9, 9, 1, 2, 1, 1, 3, 1, 9, 9, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0])。

问题根源

1. forEach遍历与数组修改冲突

forEach是基于数组初始长度遍历的,当你用splice删除元素时,数组长度缩短,后续元素会向前移位,但forEach的索引i仍按初始序列递增,这会导致部分元素被跳过或重复处理。

比如在长数组例子中,第一个零位于索引9,执行splice(9,1)后,原索引10的9会移到索引9的位置,但forEach的下一个索引是10,此时访问的是原索引11的零,直接跳过了刚移过来的9,后续的零处理也会因为索引错位出现遗漏。

2. 多余且错误的第二个判断逻辑

第二个if (finalArray[i - 1] === 0)完全是画蛇添足:

  • 当i=0时,i-1=-1,访问finalArray[-1]得到undefined,不会触发,但随着遍历推进,一旦触发该判断,splice(i-1,1)会再次修改数组,进一步打乱元素位置,导致遍历逻辑彻底混乱,非零元素可能被错误移到末尾。

3. 直接引用原数组

const finalArray = arr;只是把原数组的引用赋值给finalArray,修改finalArray等同于修改原数组,虽然这不是直接导致错误的原因,但会带来副作用(原数组被修改),不符合函数的纯性要求。

正确实现方案

方案一:创建新数组(简洁直观)

先过滤出所有非零元素,再补充对应数量的零,逻辑清晰且无副作用:

const moveZeros = (arr) => {
  const nonZeroElements = arr.filter(item => item !== 0);
  const zeroCount = arr.length - nonZeroElements.length;
  return nonZeroElements.concat(Array(zeroCount).fill(0));
};

方案二:原地修改(内存高效)

使用双指针法,先将所有非零元素移到数组前端,再将剩余位置填充为零:

const moveZeros = (arr) => {
  let nonZeroIndex = 0;
  // 移动非零元素到前端
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] !== 0) {
      arr[nonZeroIndex] = arr[i];
      nonZeroIndex++;
    }
  }
  // 填充剩余位置为零
  for (let i = nonZeroIndex; i < arr.length; i++) {
    arr[i] = 0;
  }
  return arr;
};

这两种方案都能正确处理所有测试用例,包括长零数组,且严格保留非零元素的原有顺序。

内容的提问来源于stack exchange,提问作者SeGvr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:40:29