双指针算法模板及例题

2023-10-27

双指针算法时间复杂度O(n)

一般双指针算法运用于有序的某一个或两个序列中,从O(n2)优化到O(n)

算法模板

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类:
    (1) 对于一个序列,用两个指针维护一段区间
    (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作


补充关于字串与子序列的区别:
在这里插入图片描述


第一类双指针:指向两个序列

例:归并排序,acwing2816. 判断子序列,acwing800. 数组元素的目标和
acwing800. 数组元素的目标和
在这里插入图片描述
算法一: 双指针O(n + m)

假定两个指针i指向a数组的初始位置, j指向b数组的终点
由于两个序列都是有序的, 那么如果a[i] + b[j] > x 仅仅回退j指针即可(a[i] + b[j] > x那么i往后移动必然会导致a[i] + b[j]的值会更大只有减小b[j], 才有可能使得a[i] + b[j] <= x), 当a[i] + b[j] > x,那么j就不能再回退了,若是再回退必然会导致a[i] + b[j]更小, 这时只需要不动j, 去将i指针向后移动即可,如此迭代找到a[i] + b[j] == x, 双指针优化时j指针不会每次都再回退到b数组的末尾,从而优化了时间复杂度

code:

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m, x;
int a[N], b[N];

int main()
{
    cin >> n >> m >> x;
    for(int i = 0; i < n; i ++ )    cin >> a[i];
    for(int i = 0; i < m; i ++ )    cin >> b[i];
    
    for(int i = 0, j = m - 1; i < n; i ++ )
    {
        //j > 0保证数组不会越界,这里数据保证了一定会有解,加不加都行,感觉还是习惯性还是加上好点
        while(j > 0 && a[i] + b[j] > x) j --;   
        //退出循环a[i] + b[j] <= x,那么直接判断是否等于x,等于输出,不等于就直接将i往后移动
        if(a[i] + b[j] == x)    printf("%d %d\n", i, j);
    }
    
    return 0;
}

算法二:二分O(nlogm)

#include <iostream>
using namespace std;
const int N = 1e5 + 10;

int a[N], b[N];
int n, m, x;

int main()
{
    cin >> n >> m >> x;
    for(int i = 0; i < n; i ++ )    cin >> a[i];
    for(int i = 0; i < m; i ++ )    cin >> b[i];
    
    for(int i = 0; i < n; i ++ ) 
    {
    	//二分模板,当然这里也能用lower_bound()
        int l = 0, r = m - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(b[mid] >= x - a[i])  r = mid;
            else l = mid + 1;
            
        }
        if(a[i] + b[l] == x)    cout << i << ' ' << l;
    }
    return 0;
}

acwing2816. 判断子序列
在这里插入图片描述

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m;
int a[N], b[N];

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ )    cin >> a[i];
    for(int i = 0; i < m; i ++ )    cin >> b[i];
   
    int i, j;    //i指向b数组,j指向a数组
    /* 
    	注意这里的 j < n 就必须要写了, 若是不写那么当a[]循环完时,
    	那么a[]有效值之后的全是0,此时若是b[]中也是0,j就会错误匹配导致j的值>n
		测试数据:   	a   1
					b	1 	0
	*/
    for(i = 0, j = 0; i < m; i ++)
        if(j < n && a[j] == b[i])    j ++;
      
    if(j == n)  puts("Yes");
    else puts("No");
    
    return 0;
}



第二类双指针:指向一个序列

例:快速排序, acwing799. 最长连续不重复子序列
acwing799. 最长连续不重复子序列
在这里插入图片描述

对于一个序列总要有个快慢指针,外层循环放快指针,内层循环放慢指针
对于本题,用慢指针j,与快指针i进行维护一个区间,不断更新[j, i] 区间的大小,找到最大值。
由于要求是不重复的,所以当发生重复情况,那么一定是快指针i所指向的值与上一个值重复(这里开个数组记录一下每个元素出现的次数,若次数>1说明重复了,若数据较大,可用哈希代替数组)

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], s[N];

int main()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++ )    cin >> a[i];
    
    int res = 0;
    for(int i = 0, j = 0; i < n; i ++ ) 
    {
        s[a[i]] ++;
        while(j < i && s[a[i]] > 1)     s[a[j ++ ]] --;     
        //若执行了循环,当循环结束后,j刚好指向最后一个i指向的元素,此时i, j 
        res = max(res, i - j + 1);
    }
    cout << res << endl;
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

双指针算法模板及例题 的相关文章

  • 为什么使用abs()或fabs()而不是条件否定?

    在 C C 中 为什么要使用abs or fabs 不使用以下代码即可查找变量的绝对值 int absoluteValue value lt 0 value value 这与较低级别的指令较少有关吗 您提出的 有条件的abs 并不等于std
  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • 赋值运算符和复制构造函数有什么区别?

    我不明白C 中赋值构造函数和复制构造函数之间的区别 是这样的 class A public A cout lt lt A A lt lt endl The copy constructor A a b The assignment cons
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • 如何用 kevent() 替换 select() 以获得更高的性能?

    来自Kqueue 维基百科页面 http en wikipedia org wiki Kqueue Kqueue 在内核和用户空间之间提供高效的输入和输出事件管道 因此 可以修改事件过滤器以及接收待处理事件 同时每次主事件循环迭代仅使用对
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • 是否有一个 C++ 库可以从 PDF 文件中提取文本,例如 PDFBox for Java? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 去年 我使用 PDFBox 在 Java 中创建了一个应用程序来获取某些 PDF 文件中的原始文本 现在
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 如何使用 std::array 模拟 C 数组初始化“int arr[] = { e1, e2, e3, ... }”行为?

    注意 这个问题是关于不必指定元素数量并且仍然允许直接初始化嵌套类型 这个问题 https stackoverflow com questions 6111565 now that we have stdarray what uses are

随机推荐

  • YOLOv5-Shufflenetv2

    YOLOv5中修改网络结构的一般步骤 models common py 在common py文件中 加入要修改的模块代码 models yolo py 在yolo py文件内的parse model函数里添加新模块的名称 models ne
  • 【100天精通Python】Day51:Python 数据分析_数据分析入门基础与Anaconda 环境搭建

    目录 1 科学计算和数据分析概述 2 数据收集和准备 2 1 数据收集 2 1 1 文件导入 2 1 2 数据库连接 2 1 3 API请求 2 1 4 网络爬虫 2 2 数据清洗 2 2 1 处理缺失值 2 2 2 去除重复值 2 2 3
  • 浪潮服务器NF5280M5配置管理口BMC的IP web界面登录 ipmi 代外【详细】

    开启服务器以后等待按del或f2 进入bios选择第五项Server Mgmt界面选择BMC Network Configuration 回车 选择BMC IPv4 Network Configuration 回车 注意 只需要配置BMC
  • MySQL——必考面试题 ①

    一 为什么要使用数据库 数据保存在内存 优点 存取速度快 缺点 数据不能永久保存 数据保存在文件 优点 数据永久保存 缺点 速度比内存操作慢 频繁的IO操作 查询数据不方便 数据保存在数据库 数据永久保存 使用SQL语句 查询方便效率高 管
  • unity生成vr效果

    这是一个谷歌的插件 GoogleVRForUnity unitypackage 谷歌插件下载地址 开始制作最简单的 VR 盒子 导入 GoogleVRForUnity unitypackage 将项目的平台设置为 Android 平台 在项
  • web前端DOM

    1 2 1 什么是DOM 文档对象模型 Document Object Model 简称DOM 是 W3C 组织推荐的处理可扩展标记语言 html或者xhtml 的标准编程接口 W3C 已经定义了一系列的 DOM 接口 通过这些 DOM 接
  • 2023.1.30日学习内容(多线程接收,发送文件)

    1 多线程接收文件 1 线程文件 public Socket socket public MyThread Socket socket this socket socket Override public void run try Stri
  • WordGo导出word(list)

    导出word文档 param userResume public String getWord BasUserResume userResume WordGo wordGo new WordGo wordGo add userResume
  • 计算机网络期中测验

    目录 一 单选题 二 填空题 三 判断题 一 单选题 1 单选题 采用全双工通信方式 数据传输的方向为 A 可以在两个方向上传输但不能同时进行 B 只能在一个方向上传输 C 可以在两个方向上同时传输 D 以上均不对 答案 C 解析 三种通信
  • 百度移动统计热力图和事件分析的坑

    埋点是这2年比较火的一项技术 友盟 极光推送 腾讯云 百度移动统计都相继开发了增加埋点的SDK 方便开发者使用 其中最为先进的是百度移动统计的无埋点技术 无埋点技术是不用开发者手动埋点的一项技术 很方便使用 对开发减少了开发量 太赞 集成步
  • jieba如何自行 split 或 join ?

    目录 jieba suggest freq 源码 split 关键运行过程解释 注意 使用此函数也有可能分不开 join 关键运行过程解释 jieba add word del word 源码 参考文献 jieba suggest freq
  • 联想拯救者R720 - i5-7300HQ/1050ti(macOS Big Sur/Windows) 双系统在 OpenCore (6.0.3)/ OCC (2.5.0)引导下的安装过程

    前言 重要 硬件列表 拯救者R720 处理器 型号 i5 7300HQ 架构 kaby lake 显卡 核显 UHD630 独显无效 忽略 主板 系列 100 Series 网卡 型号自选自购 不做陈列 声卡 批次不同 型号不同 不做陈列
  • [Unity好插件之PlayMaker]PlayMaker如何扩展额外创建更多的脚本

    学习目标 如果你正在学习使用PlayMaker的话 那么本篇文章将非常的适用 关于如何连线则是你自己的想法 本篇侧重于扩展适用更多的PlayMaker行为Action 那么什么是PlayMaker行为Action呢 就是这个列表 当我们要给
  • js echarts 固定颜色按顺序组合 或者随机生成颜色

    在使用echarts的时候或者大转盘的时候 数据量总是很多 但是颜色可以随机生成 也可以使用自己固定的颜色 这边我就分享了一下几种按照顺序组成颜色的代码 第一种 通过循环颜色 用一个splice 删一个 如果颜色没有了 再重新给他原来的数组
  • 常用事务代码(转)

    Pfcg 绝色维护 Su53 查看权限对象 st01 跟踪 St22 看dump 以分析错误 eg 找到ABAP程序出错的地方 找出founction 用se37查看找到的founction 找到有关权限检查 authority check
  • scscanner:一款功能强大的大规模状态码扫描工具

    关于scscanner scscanner是一款功能强大的大规模状态码扫描工具 该工具可以帮助广大研究人员从一个URL列表文件中批量读取目标网站的状态码响应信息 除此之外 该工具还可以过滤出指定的状态码 并将结果存储到一个文件中以供后续深入
  • neon常用指令(updating)

    函数参考手册 https developer arm com architectures instruction sets simd isas neon intrinsics 并在左侧选择neon Neon 128bit寄存器 所以可支持并
  • mysql将一张表插入到另一张表

    1 表1和表2的字段完全相同且要把表2所有的数据都插入到表1 可以用这种方法 insert into table1 select from table2 2 但是更多的时候我们只希望导入指定字段 可以用这种方法 insert into ta
  • 冯思远:Apache TVM 与机器学习编译发展

    下午好 欢迎大家今天来参加 2023 Meet TVM 作为 Apache TVM PMC 由我来给大家做关于 TVM 的发展以及 TVM 未来 Unity 框架的分享 Apache TVM Evolution 首先为什么会有 MLC Ma
  • 双指针算法模板及例题

    双指针算法时间复杂度O n 一般双指针算法运用于有序的某一个或两个序列中 从O n2 优化到O n 算法模板 for int i 0 j 0 i lt n i while j lt i check i j j 具体问题的逻辑 常见问题分类