首页 > 其他分享 >双指针

双指针

时间:2024-12-24 15:31:03浏览次数:3  
标签:数组 int 端点 排序 mx 指针

@

目录

双指针

基本介绍

双指针主要用于处理数组或链表等线性数据结构中的问题。它的基本思想是使用两个指针(通常是两个变量)来遍历或操作数据,这两个指针可以指向数组的开始和结束位置,也可以根据具体问题指向其他位置。双指针算法能够有效地减少时间复杂度,特别是在处理排序数组或需要查找特定条件下的元素时非常有用。

应用场景

两数之和:给定一个已排序的数组和一个目标值,找出数组中两个数,使它们的和为给定的目标值。可以通过设置一个指针从数组的开始位置,另一个指针从数组的末尾开始,向中间移动,直到找到满足条件的两个数或两个指针相遇。

移除元素:例如,在数组中移除所有出现的某个特定值,并返回新数组的长度。可以使用快慢指针的方法,快指针用于遍历整个数组,慢指针用于记录非移除元素的位置。

合并两个有序数组:将两个已排序的数组合并成一个新的有序数组。可以同时从两个数组的开头或结尾开始,比较元素大小并按顺序放入新的数组中。

链表相关问题:如判断链表是否有环、寻找链表的中间节点等。可以使用快慢指针,其中快指针每次移动两个节点,慢指针每次移动一个节点。

例题

A-B数对

题目链接: A-B数对

题目描述

给出一串正整数数列以及一个正整数 C,要求计算出所有满足 A - B = C 的数对的个数(不同位置的数字一样的数对算不同的数对)。

思路: 枚举左端点l,维护两个右端点r1,r2。具体实现看代码吧!

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 9;
int a[N];
void solve()
{
	//输入数据
	int n,c;
	cin>>n>>c;
	for(int i=1;i<=n;i++) cin>>a[i];
	//排序 后面枚举左右端点时要保证a[r]>=a[l]
	sort(a+1,a+1+n);
	//左右端点
	int l=1,r1=1,r2=1;
	ll ans=0;
	for(l=1;l<=n;l++)
	{
		while(r1<=n&&a[r1]-a[l]<=c) r1++;
		while(r2<=n&&a[r2]-a[l]<c) r2++;
		//[r2+1,r1]区间满足A-B=C
		ans+=r1-r2;
	}
	//输出答案
	cout<<ans<<'\n';
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int _ = 1;
    //cin >> _;
    while (_--) solve();
    return 0;
}

排列排序

题目链接: 排列排序

题目描述

给你一个长度为 n 的排列 p1,p2, ...... ,pn。你需要把它排序。
每次可以花区间长度,即 r-l+1 的代价,选择排列中的任意一段区间 [l,r],并将 [l,r] 从小到大排序。
现在你可以让他进行若干次这个操作,直到 p 中元素的值从 1 到 n 按升序排序,即对于 1 到 n 的每一个 i,都有 pi=i。
求问花的代价最少为多少?

思路: 首先对于a[ i ] = i 的数据,说明它处于正确的位置,不用进行排序。然后对于不满足的数据进行排序,双指针左右端点 l ,r 。l之前的元素全部都已经到了正确的位置。 此时我们要维护区间 [ l , r ] 的最大值mx,左端点 l 不动,当满足 mx > r 时右端点往右移,最终状态为 mx = r 。然后对区间 [ l , r ] 进行排序,直到 l = n 时结束。

看代码吧!

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 9;
int n,a[N];
void solve()
{
	//输入数据
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int ans=0;
	//双指针
	int l=1,r=1;
	while(l<=n)
	{
		//如果某个元素值与下标相同,则元素处于正确的位置,不用进行排序,左指针l加一
		if(a[l]==l) l++;
		//不相同,则需要进行排序
		else 
		{
			//维护区间[l,r]的最大值
			int mx=a[l];
			int r=l+1;
			mx=max(mx,a[r]);
			while(mx>r)
			{
				r++;
				mx=max(mx,a[r]);
			}
			//此时mx=r,对区间[l,r]进行排序
			//更新l和ans
			ans+=r-l+1;
			l=r+1;
		}
	}
	//输出答案
	cout<<ans<<'\n';
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int _ = 1;
    //多组数据输入
    cin >> _;
    while (_--) solve();
    return 0;
}

总结

  1. 在使用双指针之前,确保对问题的理解足够深入,明确指针的初始位置、移动规则以及停止条件。
  2. 对于不同类型的双指针问题(如快慢指针、相向而行的指针等),要灵活选择合适的策略。
  3. 注意边界条件的处理,避免出现数组越界等错误。

标签:数组,int,端点,排序,mx,指针
From: https://www.cnblogs.com/jin1/p/18627805

相关文章

  • 指针, C语言的精髓
    指针,C语言的精髓 指针,C语言的精髓莫队先咕几天,容我先讲完树剖(因为后面树上的东西好多都要用树剖求LCA,树剖求LCA比倍增求LCA常数小).什么是指针保存变量地址的变量叫做指针.这是大概的定义,但是Defad认为这个定义不太好理解,所以我们先不看.我们的电......
  • C语言——void指针和空指针的区别
    面试题1、void指针    (1)格式:void*    (2)void指针就是指向任何类型的指针        (3)在编译的时候不会确定其指向的类型,是在程序中进行指向的    (4)这种类型的指针不能直接进行取内容或递增递减的操作,必须先转成别的类型的指针才可以执行,否则......
  • c语言指针
    指针指针=>内存地址指针变量=>存储着内存地址的变量定义格式:数据类型*变量名(数据类型要跟指向的数据类型保持一样)指针作用 1.查询数据  inta=10;  int*p=&a;  printf("%d\n",*p);2.存储数据/修改数据 *p=200; printf("%d",*p);3.参数传递4......
  • 【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
    【C语言】函数指针与指针函数文章目录@[TOC](文章目录)前言一、指针数组二、数组指针三、函数指针四、指针函数五、函数指针数组六、回调函数七、参考资料总结前言使用工具:1.DEVC++提示:以下是本篇文章正文内容,下面案例可供参考一、指针数组优先级关系:()>......
  • 教你学会自定义鼠标指针
    我现在用的一款很好看的指针如下图所示:是不是真的还挺不错的,还有更多可好玩的样式:只要先下载了这个软件,这些都是可以免费使用的,看腻了就换一个!下载过后操作这个就可以直接生效了,都不用重新启动的......
  • cpp智能指针
      普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型uniqu......
  • 题山采玉:(双指针) 移动零
    嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的passion。准备好和我一起冲进代码的奇幻宇宙了吗?Let'sgo!我的博客:yuanManGan我的专栏:C++入门小馆 C......
  • Arc指针
    Arc指针在Rust中,Arc是一个线程安全的引用计数智能指针,它允许多个线程共享所有权。Arc是“AtomicReferenceCounted”(原子引用计数)的缩写,它基于原子操作实现,确保在多线程环境中引用计数的正确性和安全性。与普通的Rc(引用计数智能指针)不同,Arc是线程安全的,可以在多个......
  • C语言基础十三:常量指针、指针常量与动态内存的分配
    main函数原型定义:main函数有多种定义格式,main函数也是函数,函数相关的结论对main函数也有效(也可以定义main的函数指针)。main函数完整写法:intmain(intargc,char*argv[]){}intmain(intargc,char**argv){}注意:char*argv[]与char**argv用于字符数组指针即字......
  • 双指针解题(滑动窗口)
    概念滑动窗口属于双指针,因为左右两指针同向移动,像窗口移动而得名.练习题目长度最小的子数组209.长度最小的子数组-力扣(LeetCode)思路只要左右区间对应值之和小于目标值,则直接入窗口(即right++),且将sum加上入窗口的值;当左右区间的对应值之和大于等于目标值,则直接出窗口......