双指针1:移动零

🔥个人主页: Milestone-里程碑

❄️个人专栏: <<力扣hot100>> <<C++>><<Linux>>

<<Git>><<MySQL>>

🌟心向往之行必能至

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。注意:必须在不复制数组的情况下原地对数组进行操作。

示例

  • 输入:nums = [0,1,0,3,12]
  • 输出:[1,3,12,0,0]

方法一:双指针交换法

思路

我们可以用一个指针 left 来记录当前非零元素应该放置的位置,然后遍历数组。当遇到非零元素时,就将它与 left 位置的元素交换,并让 left 指针右移。这样可以保证 left 指针之前的所有元素都是非零的,且保持了原有顺序。

代码实现

cpp

复制代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int left = 0;
        for (auto& x : nums) {
            if (x != 0) {
                swap(x, nums[left]);
                left++;
            }
        }
    }
};

复杂度分析

  • 时间复杂度:O (n),其中 n 是数组的长度。我们只需要遍历一次数组。
  • 空间复杂度:O (1),只使用了常数级的额外空间。

方法二:覆盖补零法

思路

  1. 先遍历数组,把所有非零元素依次覆盖到数组的前面,用一个变量 stack_size 记录当前覆盖的位置。
  2. 遍历完成后,stack_size 及之后的位置全部补零即可。

代码实现

cpp

复制代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int stack_size = 0;
        // 第一步:把非零元素移到前面
        for (int x : nums) {
            if (x != 0) {
                nums[stack_size++] = x;
            }
        }
        // 第二步:后面的位置全部补零
        while (stack_size < nums.size()) {
            nums[stack_size++] = 0;
        }
    }
};

复杂度分析

  • 时间复杂度:O (n),两次遍历数组,总时间还是线性的。
  • 空间复杂度:O (1),同样是原地操作。

方法对比

方法 优点 缺点
双指针交换法 只需一次遍历,操作次数更少 交换操作会多写几次赋值
覆盖补零法 逻辑直观,容易理解 需要两次遍历,操作次数略多

在进阶要求 "尽量减少操作次数" 时,双指针交换法会更有优势。


总结

这道题的核心是原地修改保持相对顺序,两种方法都能满足要求。

相关推荐
小羊没烦恼!21 小时前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
一隅论数智21 小时前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
倒头就睡的小比特21 小时前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
LaughingZhu1 天前
Product Hunt 每日热榜 | 2026-09-19
人工智能·深度学习·神经网络·搜索引擎·百度
尧炎科技1 天前
防潮抗变形,就选纯品梅花全桉多层板
大数据
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
程序员大阳1 天前
副队长大数据教程(5)--集群情况下虚拟机网络配置
大数据·集群·nat·网路
自由能燃气设备1 天前
商用全预混低氮冷凝锅炉免费方案vs付费方案对比+选型避坑指南
大数据·数据库·人工智能
m0_547486661 天前
《数据结构教程》全套 PPT课件2026
数据结构