前言
在算法的世界里,双指针技巧常常能发挥出神奇的作用。今天,我们就来精讲两道利用双指针解决的经典题目:移动零和复写零。由于这两道题目均为数组操作,这里的双指针算法指的是利用数组下标代替指针。当我们遇到数组分块、数组划分的问题时,可以考虑使用双指针法。
双指针的作用
两个指针的主要作用如下:
cur:从左往右扫描数组,遍历整个数组。dest:已处理的区间内,非零元素的最后一个位置。
这通常将数组分为三个区间:[0, dest](全是非 0 的元素)、[dest + 1, cur - 1](都是 0)、[cur, n - 1](还未处理过的)。
移动零
题目链接:【力扣】Move Zeroes
题目描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入:nums = {0,1,0,3,12}
输出:{1,3,12,0,0}
解题思路
我们可以使用双指针法来解决这个问题。一个指针 cur 用于遍历整个数组,另一个指针 dest 用于指向当前非零元素应该放置的位置。当遇到非零元素时,将其放置在 dest 指针所指的位置,并将 dest 指针向后移动一位。遍历结束后,从 dest 指针开始到数组末尾的位置全部设置为零。
两个指针将数组分为三个区间:
[0, dest]:全是非 0 的元素(已经处理)[dest + 1, cur - 1]:都是 0(已经处理)[cur, n - 1]:还未处理过的
代码实现(以 C++ 为例)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
// dest 用于标记已处理的非零元素的最后位置
int dest = -1;
// cur 用于遍历整个向量
int cur = 0;
while (cur < nums.size()) {
// 如果当前位置的元素为 0
if (nums[cur] == 0) {
cur++;
} else {
// 先将 dest 加 1,标记下一个非零元素应放置的位置
swap(nums[++dest], nums[cur]);
cur++;
}
}
}
};


