双指针

双指针算法

相关例题

80. 删除有序数组中的重复项 II

给定一个增序排列数组 nums ,你需要在 原地 删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]

解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。你不需要考虑数组中超出新长度后面的元素。

思路分析:

首先,用变量maxRepeat=2来表示每个元素最多出现两次。定义指针slow,其初始值为maxRepeat-1=1。**

规定区间[0,slow]内的元素为最多出现两次的元素。 [0,slow]中的元素保存的是符合出现次数要求的元素集合

定义变量fast=maxRepeat=2,指向当前考察的元素。

  • 当前考察的元素nums[fast]== nums[slow-maxRepeat-1],即变量fast所指向的元素1在区间[0,slow]中已出现两次。

    因此继续考察下一个元素,fast向右移动一位。

  • 当nums[fast] != nums[slow - maxRepeat + 1],即指针fast指向的元素2不等于指针slow - maxRepeat + 1所指向的元素1,

    nums[fast]所指的元素在区间[0,slow]内,未出现超过两次,因此需要将慢指针slow向右移动一位来扩大区间。

    故slow++;接着将快指针fast指向的元素值赋予慢指针slow所指向的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<0){
return nums.size();
}
int index=2;
int n= nums.size();
for(int i=2;i<n;i++){
if(nums[index-2]!=nums[i]){
nums[index++] = nums[i];
}
}
return index;
}
};

作者:hardcore-aryabhata
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/solution/kuai-man-zhi-zhen-80-shan-chu-pai-xu-shu-4rnk/
来源:力扣(LeetCode)

75. 颜色分类

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

自己的思路:使用两个指针pv,lv; 遍历时,保证pv之前保存的都是0,保证 lv之后保存的都是2;

注意:cv计数器:遍历的范围是(0,lv] ,否则会重新调换回来;当cv所指内容是2时,cv所指元素与–lv所指元素调换之后,cv不能直接指向下一个元素; 而和++pv调换之后,cv需要直接指向下一个(因为++pv所指内容只能是1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
if(n<=1){
return;
}
else if(n==2){
if(nums[0]>nums[1]){
swap(nums[0],nums[1]);
}
return;
}
int lv = n;
int pv = -1;
for(int cv=0;cv<lv;){
if(nums[cv]==0){
swap(nums[++pv],nums[cv]);//[0,pv]--0
cv++;
}else if(nums[cv] == 2){
swap(nums[--lv],nums[cv]);//[lv,n)--2
}else{
cv++;
}
}
}
};