双指针有好几种,但是最常用的是尺取法,所以有的时候就说尺取法

双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。

分类有奇奇怪怪的几种,我写了三种

1.对撞指针(除了二分没啥用)

最经典的应用是二分
最最朴素的对撞指针就是

function fn (list) {var left = 0;var right = list.length - 1;//遍历数组while (left <= right) {left++;// 一些条件判断 和处理... ...right--;}
}

翻转数组

void reverse(int[] nums) {int left = 0;int right = nums.length - 1;while (left < right) {// swap(nums[left], nums[right])int temp = nums[left];nums[left] = nums[right];nums[right] = temp;left++;right--;}
}

2. 快慢指针

快慢指针一般都初始化指向链表的头结点 head,前进时快指针 fast 在前,慢指针 slow 在后,巧妙解决一些链表中的问题。

判链表环(图的话用这个太慢了)

单链表的特点是每个节点只知道下一个节点,所以一个指针的话无法判断链表中是否含有环的。
如果链表中不包含环,那么这个指针最终会遇到空指针 null 表示链表到头了,这还好说,可以判断该链表不含环

boolean hasCycle(ListNode head) {while (head != null)head = head.next;return false;
}

但是如果链表中含有环,那么这个指针就会陷入死循环,因为环形数组中没有 null 指针作为尾部节点。
经典解法就是用两个指针,一个每次前进两步,一个每次前进一步。如果不含有环,跑得快的那个指针最终会遇到 null,说明链表不含环;如果含有环,快指针最终会超慢指针一圈,和慢指针相遇,说明链表含有环。

boolean hasCycle(ListNode head) {ListNode fast, slow;fast = slow = head;while(fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (fast == slow)return true;}return false;
}

找链表上环的起点


这个问题其实不困难,有点类似脑筋急转弯,先直接看代码:

ListNode detectCycle(ListNode head) {ListNode fast, slow;fast = slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (fast == slow)break;}slow = head;while (slow != fast) {fast = fast.next;slow = slow.next;}return slow;
}

可以看到,当快慢指针相遇时,让其中任一个指针重新指向头节点,然后让它俩以相同速度前进,再次相遇时所在的节点位置就是环开始的位置。这是为什么呢?
第一次相遇时,假设慢指针 slow 走了 k 步,那么快指针 fast 一定走了 2k 步,也就是说比 slow 多走了 k 步(也就是环的长度)。

设相遇点距环的起点的距离为 m,那么环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。
巧的是,如果从相遇点继续前进 k - m 步,也恰好到达环起点

所以,只要我们把快慢指针中的任一个重新指向 head,然后两个指针同速前进,k - m 步后就会相遇,相遇之处就是环的起点了。

寻找链表的中点

类似上面的思路,我们还可以让快指针一次前进两步,慢指针一次前进一步,当快指针到达链表尽头时,慢指针就处于链表的中间位置。

ListNode slow, fast;
slow = fast = head;
while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;
}
// slow 就在中间位置
return slow;

当链表的长度是奇数时,slow 恰巧停在中点位置;如果长度是偶数,slow 最终的位置是中间偏右:

寻找链表中点的一个重要作用是对链表进行归并排序。
回想数组的归并排序:求中点索引递归地把数组二分,最后合并两个有序数组。对于链表,合并两个有序链表是很简单的,难点就在于二分。
这个不能用对撞吗??
不能,因为是单向的

寻找链表的倒数第 k 个元素

我们的思路还是使用快慢指针,让快指针先走 k 步,然后快慢指针开始同速前进。这样当快指针走到链表末尾 null 时,慢指针所在的位置就是倒数第 k 个链表节点(为了简化,假设 k 不会超过链表长度):

ListNode slow, fast;
slow = fast = head;
while (k-- > 0) fast = fast.next;while (fast != null) {slow = slow.next;fast = fast.next;
}
return slow;

3.左右指针

两数之和


只要数组有序,就应该想到双指针技巧。这道题的解法有点类似二分查找,通过调节 left 和 right 可以调整 sum 的大小:

滑动窗口算法/尺取法(重要)

这也许是双指针技巧的最高境界了,如果掌握了此算法,可以解决一大类子字符串匹配的问题,我第一次见是在西南民族大学第十一届程序设计竞赛(同步赛)B-都说小镇的切糕贵看到的

输入

9
bcdddbddc

输出

3

我用的二分+朴素查找挂了好多次
最后看到大佬的标称O(n)跑出

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;int l,r,ans,n,ttnum=0,used[60];
char ss[100050];
int main(){cin>>n;scanf("%s",ss);memset(used,0,sizeof(used));for(int i=0;i<n;i++){if(!used[ss[i]-'A']){ttnum++;used[ss[i]-'A']=1;}}l=ttnum;r=n;ans=n;int cnt=0;while(l<r){cnt=0;memset(used,0,sizeof(used));bool flag=false;int mid=(l+r)/2;for(int i=0;i<mid;i++){if(used[ss[i]-'A']==0){cnt++;}used[ss[i]-'A']++;if(cnt==ttnum){flag=true;break;}}for(int i=1;i<=n-mid;++i){used[ss[i-1]-'A']--;if(used[ss[i-1]-'A']==0) cnt--;if(used[ss[i+mid-1]-'A']==0){cnt++;if(cnt==ttnum){flag=1;break;}}used[ss[i+mid-1]-'A']++;}if(flag){r=mid;ans=mid;}//cout<<"OK @ "<<mid<<endl;}else {l=mid+1;}//cout<<"ERR @ "<<mid<<endl;}}cout<<l;return 0;
}

数据结构9-双指针(尺取法)(double pointer)相关推荐

  1. P2564 [SCOI2009]生日礼物(尺取法/双指针)

    LINK 不得不说 双指针用法nb 题目 输入输出样例 输入 6 3 1 5 2 1 7 3 1 3 8 输出 3 思路: 建议看尺取法 代码: #include<bits/stdc++.h&g ...

  2. 吃月饼 尺取法(双指针)

    月饼 描述 端午节都过了,中秋节还会远吗?中秋节吃月饼是我国的传统习俗.每年的中秋节,yoyo都会吃很多很多个月饼.比如蛋黄莲蓉,豆沙等等.现在,他得到了n个月饼,月饼被排成一个固定的一列.但是这个他 ...

  3. ACM—各种模拟 总结(字符串,尺取法,数学问题)习题汇总

    目录 一.字符串模拟 二. 高精度计算 1. 回文数(高精度,进制转换) 三.数学问题模拟 四.尺取法(双指针法) 1.都说小镇的切糕贵 (尺取法,字符串) umi和弓道 五.奇怪的模拟 x的位数=l ...

  4. poj2566Bound Found尺取法进阶(java)

    题目链接: 这个尺取法的思想挺好的,如果第一次做尺取法题,不妨看下尺取法入门题. 题目大意: 多组测试数据(0,0)截止. 每组数据输入 n,k(n数字个数,k询问次数) 下一行n个数表示序列. 接下 ...

  5. poj3320Jessica's Reading Problem—尺取法(java)

    题目链接 大意:给序列数字,找出最小子序列,包含所有的元素类型.例如 5 1 8 8 8 1 输出2,因为1 8就包含了所有元素 思路:尺取法 这个和裸的尺取优点不同的是,他需要一个map来维护判断而 ...

  6. poj3061尺取法/前缀和 二分(java)

    今天遇到这题因为以前没见到过,当时就是想着应该有着一个很简单的方法可以过但是奈何就是没思路.后来看了别人思路写了下来.学习了尺取法 poj3061 题目介绍: Description A sequen ...

  7. 算法篇之-----滑动窗口(尺取法)

    滑动窗口(尺取法 1. 介绍 2. 滑动窗口法的大体框架 4.最小覆盖子串 5.窗口数量 6.最小值 1. 介绍 滑动窗口法,也叫尺取法(可能也不一定相等,大概就是这样 =.=),可以用来解决一些查找 ...

  8. [SCOI2009]生日礼物 单调性尺取法

    题意:给你n个k种颜色的点,每个点都有坐标和颜色两个属性,选出一个长度尽量短的区间,使得每种颜色的点都在区间内出现. 数据范围: 对于50%的数据, N≤10000: 对于80%的数据, N≤8000 ...

  9. 解题报告 (十三) 尺取法

    文章目录 尺取法 解题报告 PKU 2100 Graveyard Design PKU 3061 Subsequence PKU 2739 Sum of Consecutive Prime Numbe ...

最新文章

  1. 中国大学的现实:层次越低,上课越多,学生读书越少
  2. Oracle SQL 空值排序(Nulls)
  3. LINQ to Entities 基于方法的查询语法
  4. B 树、B+ 树、B* 树
  5. JAVA入门级教学之(if语句)
  6. 易助erp系统服务器安装,易助ERP系统操作培训教程
  7. 如何写出吸引HR的软件测试简历
  8. 1078. Hashing (25)-PAT甲级真题
  9. ★LeetCode(538)——把二叉搜索树转换为累加树(JavaScript)
  10. 【转】如何用一个实例来探讨嵌入式软件架构设计
  11. 2022 SpringBoot/SSM的药品售货机平台 H5药品购买商城
  12. h5页面如何切图_前端切图H5/网页切图/移动自适应H5/切图开发/H5响应式
  13. Excel与对齐的文本文件互转
  14. matplotlib绘图实现中文宋体和英文Times New Roman
  15. 学习专栏-关于Python读取数据学习记录
  16. 通过wifi共享使Linux设备连接网络
  17. gogs mail 配置(邮件服务器使用自颁发证书)
  18. 计算机视觉项目-文档扫描OCR识别
  19. 单元测试与E2E测试
  20. Python 语法错误 except Exception, e: ^ SyntaxError: invalid syntax

热门文章

  1. Activiti(工作流)如何关联业务表
  2. python全栈工程师证书查询_Python全栈工程师(字符串/序列)
  3. 物流机器人也将有国家标准了!
  4. 《重修连平州志》凡例:秀才、举人、贡士、进士的区别
  5. HDLBits-Modules 题解【Verilog模块例化】(中文翻译+英文原文,可顺带学习英文)
  6. JiaoZiVideoPlayer 监听播放按钮
  7. 短视频 SDK 开发 (一) 开发一款短视频 SDK 需要具备哪些知识?
  8. 浏览器请求服务器静态文件的实现
  9. 天下最不能等待的事情莫过于孝敬自己的父母![转载]
  10. 蒋鑫鸿:9.10国际黄金原油最新外盘行情趋势点评附解一套技术指导