LeetCode 283. 移动零
题目描述
✅ 283. 移动零
思路分析
解法一:覆盖补零(推荐)
核心思路:
- 使用快慢双指针,
slow指向下一个非零元素应填入的位置,fast遍历整个数组fast遇到非零元素时,将其写入nums[slow],然后slow++- 第一次遍历结束后,
[0, slow)区间已填满所有非零元素- 第二次遍历将
[slow, n)区间全部置 0- 与 27 题(移除元素)类比:移动零本质是”移除零元素后,用 0 补全末尾”
- 优点:非零元素只写入一次,写操作次数最少,无多余交换
复杂度分析:
- 时间复杂度:O(n),其中 n 为数组长度,遍历数组两次
- 空间复杂度:O(1),原地操作,仅使用常数额外空间
class Solution {
public void moveZeroes(int[] nums) {
// slow 指向下一个非零元素应填入的位置
int slow = 0;
// 快指针遍历数组,将非零元素依次覆写到前面
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != 0) {
nums[slow] = nums[fast];
slow++;
}
}
// slow 之后的位置全部补零
while (slow < nums.length) {
nums[slow] = 0;
slow++;
}
}
}
func moveZeroes(nums []int) {
// slow 指向下一个非零元素应填入的位置
slow := 0
// 快指针遍历,将非零元素依次覆写到前面
for fast := 0; fast < len(nums); fast++ {
if nums[fast] != 0 {
nums[slow] = nums[fast]
slow++
}
}
// slow 之后的位置全部补零
for slow < len(nums) {
nums[slow] = 0
slow++
}
}
解法二:交换法
核心思路:
slow指向已处理区间的末尾,fast扫描整个数组fast遇到非零元素时,将nums[slow]与nums[fast]交换,slow++- 交换后
[0, slow)区间始终是非零元素,零自然沉底- 相比解法一多了交换操作(每次将 0 和非零元素互换),但代码更简洁
复杂度分析:
- 时间复杂度:O(n),其中 n 为数组长度,仅需一次遍历
- 空间复杂度:O(1),原地操作,仅使用常数额外空间
class Solution {
public void moveZeroes(int[] nums) {
// slow 指向已处理非零区间的下一位
int slow = 0;
for (int fast = 0; fast < nums.length; fast++) {
if (nums[fast] != 0) {
// 将非零元素交换到 slow 位置
int temp = nums[slow];
nums[slow] = nums[fast];
nums[fast] = temp;
slow++;
}
}
}
}
func moveZeroes(nums []int) {
// slow 指向已处理非零区间的下一位
slow := 0
for fast := 0; fast < len(nums); fast++ {
if nums[fast] != 0 {
// 将非零元素交换到 slow 位置
nums[slow], nums[fast] = nums[fast], nums[slow]
slow++
}
}
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 27. 移除元素 | 简单 | 双指针 |
| 26. 删除有序数组中的重复项 | 简单 | 双指针 |
| 80. 删除有序数组中的重复项 II | 中等 | 双指针 |
| 75. 颜色分类 | 中等 | 双指针 |
| 905. 按奇偶排序数组 | 简单 | 双指针 |
| 922. 按奇偶排序数组 II | 简单 | 双指针 |
| 88. 合并两个有序数组 | 简单 | 双指针 |
| 977. 有序数组的平方 | 简单 | 双指针 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!
