算法学习之双指针
2023-11-01
今天我们来学习两种算法双指针(滑动窗口)与位运算。
在数组问题中,我们可以使用两个指针分别指向数组的不同位置,根据问题的要求移动指针来进行遍历或搜索。常见的双指针技巧包括:
-
快慢指针:这种情况下,一个指针移动的速度较快(每次移动多个元素),而另一个指针移动的速度较慢(每次只移动一个元素)。这种技巧常用于解决链表中的问题,如判断链表是否有环,找到链表的中间节点等。
-
左右指针:这种情况下,一个指针从数组的左侧开始移动,而另一个指针从数组的右侧开始移动,直到两个指针相遇。这种技巧常用于解决数组中的问题,如查找数组中的某个区间、判断数组是否为回文等。
-
对撞指针:这种情况下,两个指针分别从数组的两端开始移动,并逐步向中间靠拢。这种技巧常用于解决有序数组中的问题,如在有序数组中查找两个数之和等。
以洛谷P1147为例子,这题就是典型的双指针问题,并且还附带了上一篇的前缀和问题。
题目给的数据是200万,如果我们使用朴素写法,两个for循环遍历的话,肯定超时。但是如果我们使用双指针算法,那就只需要O(n)级别的时间复杂度即可。
设定指针 i = 0, j = 0 ,因为数组是有序的,所以我们可以通过判断 sum[j] - sum[i] 和M的大小,来分别改变指针i,j的位置,并且如果a[j] - a[i] = M,则找到了答案,输出即可。
我的AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define MAX 2000005 4 typedef long long ll; 5 int M; 6 ll sum[MAX]; 7 ll a[MAX]; 8 int main(){ 9 cin>>M; 10 sum[0]=0; 11 for(int i = 1;i<=M;i++){ 12 a[i] = i; 13 sum[i] = sum[i-1] + a[i]; 14 } 15 for(int l=0,r=0;r<=M;){ 16 if(sum[r]-sum[l]<M){ 17 r++; 18 } 19 else if(sum[r]-sum[l]>M){ 20 l++; 21 r--; 22 } 23 else if(sum[r]-sum[l]==M){ 24 if(r==M) break; 25 cout<<l+1<<' '<<r<<endl; 26 l++; 27 } 28 } 29 return 0; 30 }
可以去写一下P1102 A-B 数对 是一道非常好的双指针的题。

浙公网安备 33010602011771号