(Day9)算法复健运动for蓝桥杯-双指针
(Day9)算法复健运动for蓝桥杯-双指针
先粘一个博客:素材来源https://www.cnblogs.com/luoyj/p/12408871.html
尺取法(又称为:双指针、two pointers)是算法竞赛中一个常用的优化技巧,用来解决序列的区间问题,操作简单、容易编程。
如果区间是单调的,也常常用二分法来求解,所以很多问题用尺取法和二分法都行。
另外,尺取法的的操作过程和分治算法的步骤很相似,有时候也用在分治中。
要点:
(1)一般序列都是有序的,无序的可以先排序。
(2)问题和序列的区间有关,且需要操作2个变量,可以用两个下标(指针)i、j扫描区间。
两个方向:
(a)反向扫描。i、j方向相反,i从头到尾,j从尾到头,在中间相会。
(b)同向扫描。i、j方向相同,都从头到尾,可以让j跑在i前面。
在leetcode的一篇文章中 常用的双指针技巧 https://leetcode-cn.com/circle/article/GMopsy/,把同向扫描的i、j指针称为“快慢指针”,把反向扫描的i、j指针称为“左右指针”,更加形象。快慢指针在序列上产生了一个大小可变的“滑动窗口”,有灵活的应用,例如3.1的“寻找区间和”问题。
反向扫描
例题1:找一个序列其中两个数加起来为m。(序列是有序的)
模板代码:
void find_sum(int a[], int n, int m)
{
sort(a, a + n - 1); //先排序,复杂度O(nlogn)
int i = 0, j = n - 1; //i指向头,j指向尾
while (i < j)//复杂度O(n)
{
int sum = a[i] + a[j];
if (sum > m) j--;
if (sum < m) i++;
if (sum == m)
{
cout << a[i] << " " << a[j] << endl; //打印一种情况
i++; //可能有多个答案,继续
}
}
}
在这个题目中,尺取法不仅效率高,而且不需要额外的空间。
把题目的条件改变一下,可以变化为类似的问题,例如:判断一个数是否为两个数的平方和
判断回文串:
这个自己想,一个从第一个开始跑,一个从最后一个开始跑
同向扫描
这是用尺取法产生“滑动窗口”的典型例子。
∎问题描述
给定一个长度为n的数组a[]和一个数s,在这个数组中找一个区间,使得这个区间之和等于s。输出区间的起点和终点位置。
样例输入:
15
6 1 2 3 4 6 4 2 8 9 10 11 12 13 14
6
样例输出:
0 0
1 3
5 5
6 7
说明:样例输入的第1行是n=15,第2行是数组a[],第3行是区间和s=6。样例输出,共有4个情况。
∎题解
指针i和j,i<=j,都从头向尾扫描,判断区间[i,j]的和是否等于s。
如何寻找区间和等于s的区间?如果简单地对i和j做二重循环,复杂度是O(n2)。用尺取法,复杂度O(n),操作步骤是:
(1)初始值i=0、j=0,即开始都指向第一个元素a[0]。定义sum是区间[i, j]的和,初始值sum = a[0]。
(2)如果sum等于s,输出一个解。继续,把sum减掉元素a[i],并把i往后移动一位。
(3)如果sum大于s,让sum减掉元素a[i],并把i往后移动一位。
(4)如果sum小于s,把j往后挪一位,并把sum的值加上这个新元素。
在上面的步骤中,有2个关键技巧:
(1)滑动窗口的实现。窗口就是区间[i,j],随着i和j从头到尾移动,窗口就“滑动”扫描了整个序列,检索了所有的数据。i和j并不是同步增加的,窗口像一只蚯蚓伸缩前进,它的长度是变化的,这个变化,正对应了对区间和的计算。
(2)sum的使用。如何计算区间和?暴力的方法是从a[i]到a[j]累加,但是,这个累加的复杂度是O(n)的,会超时。如果利用sum,每次移动i或j的时候,只需要把sum加或减一次,就得到了区间和,复杂度是O(1)。这是“前缀和”递推思想的应用。
下面是代码。
int i = 0, j = 0;
int sum = a[0];
while(j < n)
{ //下面代码中保证 i<=j
if(sum >= s)
{
if(sum == s)
printf("%d %d\n", i, j);
sum -= a[i];
i++;
if(i>j)
{
sum = a[i];
j++;
} //防止i超过j
}
if(sum < s)
{
j++;
sum += a[j];
}
}
“滑动窗口”的例子还有:
(1)给定一个序列,以及一个整数M;在序列中找M个连续递增的元素,使它们的区间和最大。
(2)给定一个序列,以及一个整数K;求一个最短的连续子序列,其中包含至少K个不同的元素。
在“4 典型题目”中有相似的题目。
数组去重
很简单,自己想
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!