一、双指针算法介绍
在正式讲解本次的算法题之前我们先来看看算法中一个非常常用的方法——双指针。双指针有两种形式,一种对撞指针,一种是左右指针。
1、对撞指针
一般用于顺序结构中,也称左右指针。
双指针算法包含对撞指针和快慢指针两种形式。本文通过移动零和复写零两道经典力扣题目,演示快慢指针在数组操作中的应用。移动零利用左右分区思想将非零元素前置;复写零采用从后往前遍历策略避免覆盖。文章提供详细算法流程解析及 C++ 代码实现,帮助理解原地修改数组的技巧。

在正式讲解本次的算法题之前我们先来看看算法中一个非常常用的方法——双指针。双指针有两种形式,一种对撞指针,一种是左右指针。
一般用于顺序结构中,也称左右指针。
又称龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上移动。
这种方法对于处理环形链表或数组非常有用。其实不单单是环形链表或者数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想。
快慢指针的实现方法有很多种,最常用的一种就是:


解法:(快排的思想:数组划分区间 - 数组分块)
【数组分块】是非常常见的一种算法技巧,主要就是根据一种划分方式,将数组的内容分成左右两部分。这种类型的题,一般就是使用【双指针】来解决。
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int dest = -1;
int cur = 0;
while(cur != nums.size()) {
if(nums[cur]){
swap(nums[++dest], nums[cur]);
}
cur++;
}
}
};
这里用到的方法就是我们在数据结构中学习快排算法的时候,数据划分过程的重要一步。如果将快排算法的递归拆解成单趟的话,这一小段代码就是实现快排单趟的核心步骤。



解法:(原地复写——双指针)
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
// 1. 先找到最后一个复写的数
int dest = -1;
int cur = 0;
while(1) {
dest++;
if(arr[cur] == 0) {
dest++;
}
if(dest >= arr.size() - 1) {
break;
}
cur++;
}
// 2. 处理越界情况
if(dest == arr.size()) {
arr[arr.size() - 1] = 0;
dest -= 2;
cur--;
} //之所以会越界是因为如果最后一个复写的数为 0
//则可能出现复写的位置在下标 n-1 和 n,但下标为 n 就是越界
//也就是说实际上并没有复写两遍 0 而只是数组最后一个位置复写为 0
//所以如果越界操作就是数组最后位置手动置为 0 后让 dest 回到倒数第二个位置
//cur--就是让最后一个复写的数变成前一个
// 3. 从后向前完成复写操作
while(cur >= 0) {
if(arr[cur] == 0) {
arr[dest--] = arr[cur];
}
arr[dest--] = arr[cur--];
}
}
};




微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online