首页 > 其他分享 >双指针法及例题

双指针法及例题

时间:2024-10-27 21:20:27浏览次数:7  
标签:int ++ 数组 法及 滑动 例题 我们 指针

文章目录


一、什么是双指针法

双指针法其实就是设立两个变量来模拟双重循环遍历数组的过程,它可以解决特定的双重循环问题。 这里的指针并不是真正的指针,而是用两个int型变量来记录我们遍历到的位置,由于它的作用类似于指针,所以我们把它叫做双指针法。

二、双指针的优点

双指针法常用于对数组的操作中,一般使用双指针法可以解决的问题,使用双重循环也可以解决,双指针法相当于它的一种优化方法,让数组只遍历一遍就可以求出答案,相当于将O(n^2)算法优化为了O(n)的算法,这个是非常厉害和实用的。

三、双指针常见的类型及例题

1.左右指针

左右指针其实就是让两个指针分别从数组的左右两端向中间移动,我们通过题目来理解它。

和为给定数

在这里插入图片描述
测试链接

这道题,他要求两个不同位置上和为给定数的这两个数的值,我们使用双重循环很容易可以求解,但肯定会超时,所以考虑双指针法能不能用。

  • 题目中只要求我们找到这两个数就行,且优先输出更小的数对,说明这两个数的寻找和它在数组中原本的位置是无关的,说明我们可以直接对该数组进行排序,因为给定数=一个较小数+一个较大数,且题目要求也是优先输出最小的,这样我们就不需要去判断它的大小了,找到的第一对就是最小的数对。
  • 此时,我们就可以直接用左右指针了,i指向最小数,j指向最大数,我们判断a[i]+a[j]的大小,如果>给定数,说明总和太大了,我们想要减小总和
    可以让j–,总和就减小了,反之,如果<给定数,说明此时总和太小了,我们想要增大总和,让i++,此时总和就增大了,我们循环去进行这个过程,直到找到第一个总和为给定数的时候,即可输出。

以下为代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,sum;
const int N = 1e5+10;
int a[N];
int main() {
	cin>>n;
	for (int i = 1; i <= n; i++) cin>>a[i];
	sort(a+1,a+1+n);
	cin>>m;
	int l = 1, r = n;
	while (l < r) {
		if (a[l] + a[r] == m) {
			cout<<a[l]<<" "<<a[r];
			break; 
		}
		else if (a[l] + a[r] > m) r--;
		else l++;
	}
	if (l == r) cout<<"No";
	return 0;
}

关于左右指针我们就介绍到这里,因为左右指针其实常用到的不多,题目也比较简单,而另一种类型非常常见。

2.滑动窗口

滑动窗口其实也叫快慢指针,由于它的两个指针是时刻在变化的,像一个滑动的窗口,所以我们也叫它滑动窗口,它通常用于求一段满足特殊条件的数组段,而且这个数组段的长度是不固定的,也就是我们求解前并不知道满足题目要求的数组段到底是多长,我们可以通过题目去理解理解。

(1)连续自然数和

在这里插入图片描述
测试链接

这道题要求我们求一个连续的自然数段,使这一段的总和为M。

  • 我们看到在数组中求一段满足条件的数组段时,其实可以直接去优先考虑滑动窗口,像这道题,我们可以设置两个指针i和j,让i一直向后遍历数组,j不动,直到从i到j的这段区间里面数的和=M的时候,我们就可以停止了,说明我们找到了第一个区间段,而如果没有=M而是直接>M了,说明这一段不满足条件,直接让j++,判断此时是否满足<M,重复去判断,直到i遍历完整个数组,就可以结束了。
  • 有的小伙伴会问,为什么>M的时候直接让j++后再去判断它的总和,不用让i在回来重新从j后面开始遍历呢?这就提现到我们之后使用滑动窗口的特性了,一般使用滑动窗口时,这个数组先得有序,例如,我们这个问题中,连续自然数,必然是有序的,当我们i到j不满足的时候,我们让j++,此时总和必然是减小的,我们没有必要再让i回来了,直接让它继续接着遍历后面的数去判断,没有了这个回溯的过程,我们的时间复杂度大大被优化,减少了做重复的判断,这也是双指针的美妙所在。

(2)强迫症

在这里插入图片描述

这道题,它要求在给定数组中,找到一段子数组,让该子数组中最大值和最小值的差值不超过K。

  • 我们要找的这段数组和它输入的顺序是无关的,我们只需要在数组中找到几个数,满足最大差值不超过K即可,所以我们考虑先对输入的数组进行排序,这样我们就不需要去找最大和最小数了,最左边就是最小数,最右边就是最大数,也符合滑动窗口的特性。
  • 这个题和上一道本质上是一样的,只是让你判断的条件改变了,这道题要求的最大差值不超过K,即让 a[r]- a[l] 的值与K判断即可,大于K,说明差值大了,要缩小差值,所以l往右走,反之,r往右走,这里不在赘述。

以下为代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int a[N];
int n,k,t;
int main() {
	cin>>t;
	while (t--) {
		int ans = 0;
		cin>>n>>k;
		for (int i = 0; i < n; i++) cin>>a[i];
		sort(a,a+n);
		int l = 0, r = 0;
		while (l < n && r < n) {
			if (r+1 < n && a[r+1] - a[l] <= k) r++;
			else {
				ans = max(ans,r-l+1);
				l++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

四、总结

双指针的题目特征很明显,大家多做几道就会发现,它的数组一般是有序的,而且很多题不同之处也就是判断的条件不同,大家要灵活判断条件。

大家有什么问题可以直接在评论区讨论,如有错误,欢迎指正!

标签:int,++,数组,法及,滑动,例题,我们,指针
From: https://blog.csdn.net/2301_80186482/article/details/143274716

相关文章

  • 指针入门讲解
    一.指针的定义1.引入   1.指针是内存中一个最小单元的编号,也就是地址。   2.平时我们口头中说的指针是指指针变量。   总结:指针就是地址,口语中说的指针是指指针变量。内存地址一个字节0xFFFFFFFF一个字节0xFFFFFFFE............一个字节0x00000000  ......
  • leetCode-双指针
     移动零classSolution{publicvoidmoveZeroes(int[]nums){intn=nums.length;intslow=0;intfast=0;while(fast<n){if(nums[fast]!=0){nums[slow++]=nums[fast++];......
  • CSP/信奥赛C++刷题训练:经典二分例题(2):洛谷P1678:烦恼的高考志愿
    CSP/信奥赛C++刷题训练:经典二分例题(2)烦恼的高考志愿题目背景计算机竞赛小组的神牛V神终于结束了高考,然而作为班长的他还不能闲下来,班主任老t给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是v神太忙了,身后还有一群小姑娘等着和他约会,于是他想到了同为计......
  • 给函数传入结构体和传入该结构体的指针的区别
    给函数传入结构体和传入该结构体的指针在C/C++中有以下几个关键区别:1.传递方式传入结构体(按值传递):当把结构体按值传递给函数时,函数会创建一个结构体的副本。这意味着函数中对结构体的任何修改都不会影响原始结构体的数据,因为修改的只是副本。副本是结构体的一个独立拷......
  • 数组指针的相关知识
    1.数组指针的概念    1.顾名思义,数组指针就是指向数组的指针(地址),要和指针数组做区分。    数组指针:类型为int(*)[常量],是一个地址。    指针数组:是由int*类型之类的指针为元素的数组,是一个数组。    2.数组指针指向的是整一个数组,而非......
  • 指针(进阶)
    1.字符指针2.数组指针3.指针数组4.数组传参和指针传参5.函数指针6.函数指针数组7.指向函数指针数组的指针8.相关的练习指针的主题,我们在初级阶段的《指针》已经接触过了,我们知道了指针的概念:1.指针就是个变量,用来存放地址,地址唯一标识一块内存空间。2.指针......
  • 简单区分常量指针和指针常量的小技巧
    指针常量和常量指针介绍推荐一个文章,有介绍指针常量和常量指针,本文就不做另外的篇幅去介绍彻底理解——指针常量和常量指针、指向常量的常指针-CSDN博客区分的方法该方法简单好用,掌握了以后就再也不会分不清这两个东西了只要记住这句话:const默认是修饰它左边的符号的,如果左......
  • C语言——数组、指针、函数
    目录1、数组、指针、函数2、数组指针及指针数组2.1、数组指针2.2、指针数组2.3、区别3、指针函数与函数指针3.1、指针函数3.2、函数指针3.3、区别4、所有组合1、数组、指针、函数    在前面我们已经学习了数组、指针以及函数,看起来都没有难的地方,我自认......
  • 滑动窗口与双指针
    1.定长滑动窗口套路参考:灵神的总结入-更新-出:入:下标为i的元素进入窗口,更新相关统计量。如果i<k−1则重复第一步。更新:更新答案。一般是更新最大值/最小值。出:下标为i−k+1的元素离开窗口,更新相关统计量。for(inti=0;i<nums.size();++i){//1.进入......
  • 【C语言】指针的运算
    目录1.指针加减整数2.指针减指针3.指针间的关系运算1.指针加减整数指针加减整数并不是简单的地址加减。在计算机内存中,每个变量都有一个唯一的存储位置,这个位置由其地址表示。当你对指针执行加法或减法操作,并传递一个整数值,实际上是改变了指针指向的位置,使其指向新......