数组零值移动末尾
将数组中的 0 移动到末尾,保持非零元素相对顺序
问题
给定一个数组,将所有 0 移动到数组末尾,同时保持非零元素的相对顺序。
要求原地操作,不能创建新数组。
// 输入
[0, 1, 0, 3, 12]
// 输出
[1, 3, 12, 0, 0]
解答
双指针法(推荐)
function moveZeroes(nums) {
let slow = 0; // 指向下一个非零元素应该放置的位置
// 第一次遍历:将非零元素前移
for (let fast = 0; fast < nums.length; fast++) {
if (nums[fast] !== 0) {
nums[slow] = nums[fast];
slow++;
}
}
// 第二次遍历:将剩余位置填充 0
for (let i = slow; i < nums.length; i++) {
nums[i] = 0;
}
return nums;
}
// 测试
console.log(moveZeroes([0, 1, 0, 3, 12])); // [1, 3, 12, 0, 0]
console.log(moveZeroes([0, 0, 1])); // [1, 0, 0]
单次遍历交换法
function moveZeroes(nums) {
let slow = 0;
for (let fast = 0; fast < nums.length; fast++) {
if (nums[fast] !== 0) {
// 交换 slow 和 fast 位置的元素
[nums[slow], nums[fast]] = [nums[fast], nums[slow]];
slow++;
}
}
return nums;
}
非原地操作(面试时说明取舍)
function moveZeroes(nums) {
const nonZeros = nums.filter(n => n !== 0);
const zeros = new Array(nums.length - nonZeros.length).fill(0);
return [...nonZeros, ...zeros];
}
关键点
- 双指针:
slow记录非零元素应放置的位置,fast遍历数组 - 原地操作的空间复杂度为 O(1),时间复杂度为 O(n)
- 交换法只需一次遍历,但交换次数可能更多
- 非原地方法代码简洁,但空间复杂度为 O(n)
- 注意保持非零元素的相对顺序
目录