当前位置:   article > 正文

数据结构-双指针法

数据结构-双指针法

介绍 

双指针法是一种可以在O(n)时间复杂度内解决数组、链表、字符串等数据结构相关的问题的方法。核心思想为使用两个指针在不同位置遍历数组或链表,从而实现特定操作。

常见的双指针法有

1.快慢指针:快指针每次移动两步,慢指针移动一步,用于判断链表是否有环或者找到链表中间结点等;

2.左右指针:左指针指向数组开头,右指针指向结尾,用于解决二分查找、两数之和等等;

3.滑动窗口:维护一个特定窗口,用两个指针表示左右边界,寻找符号要求的子序列;

4.对撞指针:左指针从起始位置开始遍历,右指针从末尾遍历,满足条件的情况下移动左右指针,用于解决回文串等问题

滑动窗口指针例题

洛谷P1638 逛画展

42b60f2acde247d0b51118293f385b30.png

我们需要用两个指针来维护一个没有最小的、具备所有画师作品的子序列,首先就需要先设置左指针指在开头,右指针不断向右移动,每次移动后判断是否满足具备所有画师作品,再找出其中最短的子序列

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int a[1000001];
  4. int b[10000]={0};
  5. int main() {
  6. int n,m;
  7. cin>>n>>m;
  8. int res=1,len=n;
  9. int s,e;
  10. for (int i=1; i<=n; i++) cin>>a[i];
  11. int l=0;//从左端开始寻找
  12. int r=0;
  13. b[a[0]]=1;
  14. while(r<=n&&l<=r) {//在所有样例中开始用滑动窗口查找
  15. if (res==m) {//当具备所有画师画作时
  16. if (len>r-l+1) {//找出最小区间并记录。题中要求找出第一个最小区别,因此不加等号
  17. len=r-l+1;
  18. s=l;
  19. e=r;
  20. }
  21. b[a[l]]--;//窗口向左边缩进,继续向右寻找
  22. if (b[a[l]]==0) res--;
  23. l++;
  24. } else {
  25. r++;//当不具备所有画师画作时,窗口向右延展
  26. if (b[a[r]]==0) res++;
  27. b[a[r]]++;
  28. }
  29. }
  30. cout<<s+1<<" "<<e+1;
  31. return 0;
  32. }

洛谷P8783 [蓝桥杯2022省B]统计子矩阵 

4918477986a94e65ae31b49361fd0c46.png

这道题目难点在于能想到将它压缩为一维数列,当压缩为一维数列时,利用滑动窗口可以实现符号要求的子序列的查找。每次寻找的符合要求的边界,直接加上其中的子矩阵数,就可以得到总数

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. long long a[501][501];//注意数据类型
  4. long long b[501];
  5. long long sum[510][510];//记录前缀和
  6. signed main() {
  7. long long n,m,k;
  8. cin>>n>>m>>k;
  9. for (long long i=1; i<=n; i++) {
  10. for (long long j=1; j<=m; j++) {
  11. cin>>a[i][j];
  12. }
  13. }
  14. for (long long j=1; j<=m; j++) {
  15. for (long long i=1; i<=n; i++) {
  16. sum[i][j]=sum[i-1][j]+a[i][j];//计算前缀和
  17. }
  18. }
  19. long long res=0;
  20. for (long long i=1; i<=n; i++) {
  21. for (long long j=i; j<=n; j++) {
  22. for (long long c=1; c<=m; c++)
  23. b[c]=sum[j][c]-sum[i-1][c];
  24. long long l=1,r=0;//开始利用双指针寻找子矩阵
  25. long long s=0;//记录所找矩阵中数值总和
  26. while(r<m) {
  27. r++;
  28. s+=b[r];
  29. if (s<=k) {//小于等于目标值,则继续移动
  30. res+=r-l+1;//每次移动,多出的满足条件的矩阵数为r-l+1
  31. } else {
  32. while(s>k) {//和大于时目标值,窗口从左边进行压缩
  33. s-=b[l];
  34. l++;
  35. }
  36. res+=r-l+1;
  37. }
  38. }
  39. }
  40. }
  41. cout<<res<<endl;
  42. return 0;
  43. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/117651
推荐阅读
相关标签
  

闽ICP备14008679号