如何不使用push等原生函数实现数组排序移零至末尾并合并方法?
问题描述
给定数组:
const myArray = [1, 543, 0, 232, 1, 45654, -5, 0, 7, 4, 0, 43, 77, 0, 77, 0]
需要完成两个操作:
- 将数组按升序排列
- 将所有
0移至数组末尾
预期输出:
[-5, 1, 1, 4, 7, 43, 77, 77, 232, 543, 45654, 0, 0, 0, 0, 0]
目前已实现排序功能的代码:
function sorting(arr) { for(let i = 0; i < arr.length; i++) { for (let j = 0; j < arr.length - i -1; j++) { if(arr[j+1] < arr[j]) { [arr[j+1], arr[j]] = [arr[j], arr[j+1]]; } } } return arr; }
移零功能使用了push原生函数,实现代码如下:
function moveZeros(arr) { let newArray = []; let counter = 0; for (let i = 0; i < arr.length; i++) { if(arr[i] !== 0) { newArray.push(arr[i]); } else { counter++; } } for (let j = 0; j < counter; j++) { newArray.push(0); } return newArray; }
现在有两个疑问:
- 是否存在不使用
push等原生函数的移零实现方法? - 如何将排序与移零方法合并为一个函数?
解决方案
一、不使用push的移零实现
可以用索引直接赋值的方式实现,完全不需要依赖push:
function moveZerosWithoutPush(arr) { const newArray = new Array(arr.length); // 提前创建和原数组长度一致的空数组 let nonZeroIndex = 0; let zeroCount = 0; // 先把非零元素按顺序放到新数组前面 for (let i = 0; i < arr.length; i++) { if (arr[i] !== 0) { newArray[nonZeroIndex] = arr[i]; nonZeroIndex++; } else { zeroCount++; } } // 剩下的位置全部填0 for (let i = arr.length - zeroCount; i < arr.length; i++) { newArray[i] = 0; } return newArray; }
思路很简单:先定好新数组的长度,用变量记录非零元素该放的位置,填完非零元素后,在数组末尾的对应位置直接赋值0就行。
二、合并排序与移零为单个函数
有两种实现方式,一种是整合现有逻辑,另一种是优化排序规则一步到位:
方式1:整合现有排序和移零逻辑
直接把排序和移零的步骤放到同一个函数里,用不依赖push的移零方法:
function sortAndMoveZeros(arr) { // 第一步:冒泡排序(先复制原数组,避免修改原数据) const sortedArr = [...arr]; for(let i = 0; i < sortedArr.length; i++) { for (let j = 0; j < sortedArr.length - i -1; j++) { if(sortedArr[j+1] < sortedArr[j]) { [sortedArr[j+1], sortedArr[j]] = [sortedArr[j], sortedArr[j+1]]; } } } // 第二步:不使用push的移零操作 const result = new Array(sortedArr.length); let nonZeroIdx = 0; let zeroCount = 0; for (let i = 0; i < sortedArr.length; i++) { if (sortedArr[i] !== 0) { result[nonZeroIdx] = sortedArr[i]; nonZeroIdx++; } else { zeroCount++; } } for (let i = sortedArr.length - zeroCount; i < sortedArr.length; i++) { result[i] = 0; } return result; }
方式2:优化排序规则,一步完成排序+移零
可以直接修改冒泡排序的交换条件,让排序过程同时完成移零,效率更高:
function sortAndMoveZerosOptimized(arr) { const arrCopy = [...arr]; const len = arrCopy.length; for (let i = 0; i < len; i++) { for (let j = 0; j < len - i - 1; j++) { // 交换规则:要么当前元素是0,要么当前元素大于下一个非零元素,就交换 const shouldSwap = (arrCopy[j] === 0) || (arrCopy[j] > arrCopy[j+1] && arrCopy[j+1] !== 0); if (shouldSwap) { [arrCopy[j], arrCopy[j+1]] = [arrCopy[j+1], arrCopy[j]]; } } } return arrCopy; }
这个方法的核心是调整冒泡排序的判断逻辑:遇到0就优先和后面的非零元素交换,同时正常给非零元素做升序排序。这样一轮排序完成后,所有0都会被“挤”到数组末尾,非零元素也刚好是升序排列,一步到位。
内容的提问来源于stack exchange,提问作者Leo Messi
相关产品推荐
相关产品推荐

