1. 移动零问题概述
今天我们来深入探讨一道经典的数组操作题目——移动零。这道题看似简单,却蕴含着数组操作的精髓,也是面试中经常考察的基础算法题之一。
1.1 问题定义
给定一个整数数组nums,要求将所有0移动到数组的末尾,同时保持非零元素的相对顺序不变。关键约束条件是必须原地修改数组,不能使用额外的数组空间。
这个问题在实际开发中也有应用场景,比如:
- 处理数据时需要过滤掉无效值(用0表示)但保留有效数据顺序
- 内存优化时需要将空位集中管理
- 某些算法预处理阶段需要将特定值移动到一端
1.2 题目示例分析
让我们看两个典型示例:
示例1:
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]
示例2:
输入:[0]
输出:[0]
从示例可以看出,无论数组中有多少个0,最终它们都应该出现在数组末尾,而非零元素的原始顺序必须保持不变。特别要注意边界情况,比如数组中只有一个元素时的情况。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 双指针解法详解
2.1 双指针基本思路
双指针法是解决这个问题的最高效方法,时间复杂度O(n),空间复杂度O(1)。其核心思想是使用两个指针(实际上是数组索引)来协同工作:
- 快指针(fast):负责遍历整个数组,寻找非零元素
- 慢指针(slow):标记下一个非零元素应该放置的位置
2.2 实现步骤拆解
具体实现可以分为三个阶段:
-
初始化阶段:
- 设置slow和fast都从0开始
-
非零元素前移阶段:
- fast指针遍历数组
- 当nums[fast]≠0时,将其值赋给nums[slow],然后slow++
- 无论是否找到非零元素,fast都继续前进
-
补零阶段:
- 当fast遍历完成后,从slow开始到数组末尾全部赋值为0
2.3 代码实现与优化
基础版C语言实现:
c复制void moveZeroes(int* nums, int numsSize) {
int slow = 0;
// 移动非零元素
for (int fast = 0; fast < numsSize; fast++) {
if (nums[fa
