【LeetCode Hot 100】移动零

1. 移动零

题目链接LeetCode 移动零

问题描述

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

  • 必须原地操作,不能拷贝数组
  • 尽量减少操作次数

示例

示例1
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]

示例2
输入:[0]
输出:[0]

解题思路

双指针法(最优解)

  1. 快慢指针:使用两个指针leftright
  2. 指针分工
    • right指针遍历数组
    • left指针标记非零元素的插入位置
  3. 操作过程
    • nums[right] != 0时,交换nums[left]nums[right]
    • 保持left左侧都是非零元素

将上述思路整理后改写成下面的代码版本:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        //双指针,用一个tag表示 当遍历到i不为0时,[tag , i-1]都是0
        //每次把非0的与tag交换,tag再++ , 第i位也会变成0
        int tag = 0;    //初始时为0
        for (int& x : nums)
        {
            if ( x )
            {
                swap(nums[tag++] , x);
            }
        }
    }
};

复杂度分析

• 时间复杂度:O(n),只需遍历数组一次

• 空间复杂度:O(1),只使用了常数个额外空间

关键点说明

  1. 原地操作:直接在原数组上进行修改,不创建新数组
  2. 保持顺序:非零元素的相对顺序保持不变
  3. 高效性:只需一次遍历即可完成操作
  4. 边界处理:自动处理全零数组或单元素数组的情况

扩展思考

  1. 如果要求将所有零移动到数组开头而非末尾,该如何修改算法?
  2. 如何统计移动零的总操作次数?
  3. 这种方法是否适用于其他特定值的移动(如移动所有1)?

提示:在实际编程中,可以尝试用不同的指针命名方式(如slow/fast)来帮助理解算法逻辑

posted on 2025-05-18 11:00  无穷小学弟  阅读(32)  评论(0)    收藏  举报

导航