LeetCode 补拙笔记 日期:2026.06.07 题目:283. 移动零

LeetCode 补拙笔记

0. 前言

  • 日期:2026.06.07
  • 题目:283. 移动零
  • 难度:简单
  • 标签:数组、双指针

1. 题目理解

问题描述

给定一个数组 nums,将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序

  • 必须在原地对数组进行操作,不允许复制数组。

示例

输入:nums = 0,1,0,3,12

输出:1,3,12,0,0

2. 解题思路

核心观察

  • 非零元素的相对顺序必须保持不变,因此可以用双指针 实现:
    1. 一个慢指针 j 指向"下一个非零元素应该存放的位置";
    2. 一个快指针 i 遍历数组,遇到非零元素就和 j 位置的元素交换,然后 j++
  • 这种方法能保证非零元素的相对顺序不变,且所有操作在原地完成。

算法步骤

  1. 初始化慢指针 j = 0
  2. 遍历数组:
    • nums[i] != 0,则交换 nums[i]nums[j]
    • 交换后 j++
  3. 遍历结束,所有非零元素已移至数组前部,零元素自然落在末尾。

3. 代码实现

java 复制代码
package lc283;

class Solution {
    public void moveZeroes(int[] nums) {
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
                j++;
            }
        }
    }
}

4. 代码优化说明

java 复制代码
class Solution {
    static {
        // 预热代码,优化首次运行性能
        Solution s = new Solution();
        int[] t= {1};
        for(int i=0;i<500;++i){
            s.moveZeroes(t);
        }
    }
    public void moveZeroes(int[] nums) {
        // zeroIndex 记录当前第一个0的位置
        int zeroIndex = -1;
        int len = nums.length;
        for (int i = 0; i < len; ++i) {
            if (nums[i] != 0) {
                // 如果前面存在0,则将当前非零元素移动到第一个0的位置
                if (zeroIndex >= 0) {
                    nums[zeroIndex] = nums[i];
                    nums[i] = 0;
                    // 更新第一个0的位置,向后寻找下一个0
                    for (int j = zeroIndex + 1; j <= i; ++j) {
                        if (nums[j] == 0) {
                            zeroIndex = j;
                            break;
                        }
                    }
                }
            } else {
                // 遇到第一个0时记录位置
                if (zeroIndex == -1) {
                    zeroIndex = i;
                    continue;
                }
            }
        }
    }
}

5. 复杂度分析

  • 双指针交换法(基础版)
    • 时间复杂度:O(n)O(n)O(n),每个元素最多被访问一次。
    • 空间复杂度:O(1)O(1)O(1),原地操作,仅使用常数额外空间。
  • 优化版(单指针+查找下一个0)
    • 时间复杂度:最坏情况下为 O(n2)O(n^2)O(n2)(全零数组),但实际运行中常数优化明显,性能表现通常优于基础版。
    • 空间复杂度:O(1)O(1)O(1),原地操作。

6. 总结

  • 核心思路:利用双指针在原地完成非零元素的"前移",同时保持其相对顺序。
  • 优化点:
    1. 避免不必要的交换:仅在当前元素非零且前面存在零时才进行移动;
    2. 提前预热JVM:通过静态代码块减少首次运行的性能开销;
    3. 减少if分支:逻辑更紧凑,提高执行效率。
  • 关键技巧:j 指针只在遇到非零元素时移动,保证了非零元素的相对顺序不变。
相关推荐
珠海西格电力12 分钟前
零碳园区数据应用的具体场景有哪些?
大数据·人工智能·算法·架构·能源
北鸟南游25 分钟前
学习-claude code 工程化实战的笔记-极客时间
笔记·学习·ai编程
geovindu30 分钟前
CSharp: Dijkstra Algorithms
开发语言·后端·算法·c#
解局易否结局35 分钟前
鸿蒙PC应用开发:窗口管理 + 鼠标键盘交互 + 文件对话框
笔记·华为·计算机外设·交互·harmonyos
三品吉他手会点灯43 分钟前
嵌入式机器学习 - 学习笔记1.0.2 - 学习路线导览:从机器学习基础到 TinyML应用
人工智能·笔记·嵌入式硬件·学习·机器学习
学逆向的1 小时前
汇编——位运算
开发语言·汇编·算法·网络安全
可编程芯片开发1 小时前
基于simulink的PEM燃料电池控制系统建模与仿真,对比PID,积分分离以及滑模控制器
算法
学究天人1 小时前
数学公理体系大全:Comprehensive Collection of Mathematical Axiom Systems(卷2)
算法·数学建模·动态规划·图论·抽象代数·拓扑学
m0_669649462 小时前
医院发电机:安装与维护的区别要点
笔记
玛卡巴卡ldf2 小时前
【LeetCode 手撕算法】(细节知识点总结)
java·数据结构·算法·leetcode·力扣