1. 双指针介绍
常见的双指针有两种形式,一种是对撞指针,一种是快慢指针。
对撞指针:一般用于顺序结构中,也称左右指针。
- 对撞指针从两端向中间移动。一个指针从最左端开始,另一个从最右端开始,然后逐渐往中间逼近。
- 对撞指针的终止条件一般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循环),也就是:
left == right(两个指针指向同一个位置); left > right(两个指针错开);
**快慢指针:**又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上移动。
这种方法对于处理环形链表或数组非常有用。其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想。
快慢指针的实现方式有很多种,最常用的一种是:一次循环中,每次让慢指针向后移动一位,而快的指针向后移动两位,实现一快一慢。
2. 移动零
题目链接:283. 移动零
题目描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
解题思路
这题我们使用双指针解决,需要一个 cur 指针和一个 dest 指针,将数组划分成 3 个区间,[0, dest] 的元素全部是非 0 元素,[dest + 1, cur - 1] 的元素全是 0,[cur -1, n - 1] 的元素是待处理的。
具体流程如下:
-
初始化 cur = 0(用于遍历数组),dest = -1(指向非 0 元素的最后一个位置,由于刚开始我们不知道最后一个非 0 元素在什么位置,因此初始化为 -1)
-
cur 依次往后遍历每个元素。
- 当 cur 遇到 0 时,cur++
- 当 cur 遇到非 0 时,dest++,交换 dest 的位置与 cur 位置的值
C++代码实现
class Solution {
public:
void moveZeroes(vector<int>& nums) {
for (int cur = 0, dest = -1; cur < nums.size(); cur++) {
if (nums[cur] != 0 && ++dest!= cur) {
swap(nums[dest], nums[cur]);
}
}
}
};
时间复杂度:O(n)
空间复杂度:O(1)
3. 复写零
题目链接:1089. 复写零


