双指针算法专题:移动零与复写零
一、移动零
题目描述
算法原理
数组划分即数组分块,按要求将数组划分为不同模块。例如本题,将数组划分为前部非零和后部零两部分。
使用两个指针 dest 和 cur 将数组划分为三个区间:
- cur:从左向右扫描数组,遍历数组,cur 左边是已处理区域,右边是未处理区域。
- dest:已处理区间内最后一个非 0 的位置。
当 cur 到达 n 时,最后一个区间消失,仅剩前两个区间,前边是非 0,后边是 0。 cur 指向第一个元素,dest 初始指向 -1。
cur 移动时遇到两种情况:
- 遇到 0 时,cur++,保证 [dest+1, cur-1] 区间为 0。
- 遇到非 0 时,将该值加入第一个区间 [0, dest],dest 移动到下一个位置扩大该区间,并交换此时 dest 和 cur 的位置。
代码实现
class Solution {
public:
void moveZeroes(vector<int>& nums) {
for (int dest = -1, cur = 0; cur < nums.size(); cur++) {
// cur 每轮都 ++,所以不用单独写 cur 遇到 0 的情况
if (nums[cur]) {
// 遇到非 0 元素时
swap(nums[++dest], nums[cur]);
}
}
}
};
二、复写零
题目描述
算法原理
双指针法,先根据'异地'操作,然后优化到'就地'操作。
问题难点:直接在原数组上操作会覆盖后续元素。
解决方案:分两步操作。
第一步:定位最后一个需要复写的元素
使用双指针模拟复写过程:
cur:遍历原数组dest:跟踪在新数组中的位置
特殊规则:
- 遇到非零元素:
dest移动 1 位 - 遇到零元素:
dest移动 2 位(因为零需要被复写)


