基本思想:
我们在遍历对象的过程中,不单独使用一个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,根据不同题目的要求进行判断,从而达到相应的目的。
常见问题分类:
(1) 对于一个序列,用两个指针维护一段区间
(2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作
给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
输入格式
第一行包含整数 n。
第二行包含 n 个整数(均在 0∼10^5 范围内),表示整数序列。
输出格式
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
数据范围
1≤n≤10^5
输入样例:
5
1 2 2 3 5
输出样例:
3
#include<iostream> using namespace std; const int N=1e5+10; int a[N],s[N]; int n; int main(){ cin>>n; for(int i=0;i<n;i++) cin>>a[i]; int ans=0; //可模板化记忆双指针用法 注意题目要求的条件即可 for(int i=0,j=0;j<n;j++){//用j来遍历一遍 i每次都小于j 循环次数不超过2n 即将暴力算法O(n^2)->O(n) s[a[j]]++; while(i<=j&&s[a[j]]>1){ s[a[i]]--; i++; }//用s[]来判断子序列是否有重复 如果有重复的, //比如10 //9 3 6 6 5 10 1 2 3 9 //当j遍历到下标为3的6时,6出现了两次,进入while循环,将前面的逐一排查到和a[j]重复的元素那里更新i的位置,即将i变为了3,再继续查找是否 //有比3更长的连续不重复子序列 ans=max(ans,j-i+1); } cout<<ans<<endl; return 0; }
例题:
800. 数组元素的目标和 - AcWing题库 //多用反向思维
剑指 Offer 05. 替换空格 - 力扣(LeetCode)
15. 三数之和 - 力扣(LeetCode)//难点在如何恰当的去剪枝去重
//蒟蒻的记录 剪枝多了之后需要考虑的更加全面 也得耐下心来做