双指针算法模板和应用

2023-11-06

目录

模板

应用场景

例题

 注意这种写法会出现 Segmentation Fault   


模板

	for (int i = 0, j = 0; i < n; i ++ )
	{
		while (j < i && check(i, j)) j ++ ;
		
		// 具体问题的逻辑
	}
	常见问题分类:
		(1) 对于一个序列,用两个指针维护一段区间
		(2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

应用场景

对于需要双重循环的操作我们把这两个循环的变量设为i,j,那么i,j就是两个指针
例如:for(int i = 0; i < n; i ++ )
                    for(int j = 0; j < n; j ++ )
 其中j需要回溯:因为每一次j都要从一个固定的数(这里为0)开始,无论上一次循环j在什么位置。这样的时间复杂度为O(n^2)

而我们的双指针算法就是要让j不回溯,j直线的从0走到n,那么这样的时间复杂度就是O(2n),即O(n)

综上所述:双指针算法就是通过避免回溯操作将朴素O(n^2)优化到O(2n)即O(n)


例题

799. 最长连续不重复子序列 - AcWing题库

 思路:

1.如何判断重复:因为本题数据范围较小,我们可以设置一个s数组来保存每一个值的数量

2.什么时候出现重复:因为我们枚举的是i,所以当元素出现重复的时候,一定是新加入的a[i]与原来的值重复了

3.怎么让j不回溯:在本题中,指针j只能前进不能后退。因为如果j可以后退,说明上一个i对应的指针j构成的区域没有重复的值,说明上一步的j也可以后退一步,这就互相矛盾了,因为我们上一个i对应的i和j构成的区域已经确保是最大的无重复元素的区域了。

4.指针移动带来的变化:如果指针i移动,那么指针i移动后指向的值的数量+1,如果指针j移动,那么j移动前指向的值的数量-1。

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
int a[N], s[N];

int main()
{
    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]] ++;    //指针i指向的值的数量+1
        while(s[a[i]] > 1)    //只要刚加入的a[i]让序列中存在重复元素
        {
            s[a[j]] --;    //j前进之前指向的值的数量-1
            j ++;    //j前进
        }
        res = max(res, i - j  + 1);
    }
    
    cout << res << endl;
    
    return 0;
}

800. 数组元素的目标和 - AcWing题库

考虑如何让j不回溯:

(1)j从0开始出发:因为两个序列是递增的,所以当指针j停下,即a[i] * b[j] > x的时候,我们移动指针i,这时候可能a[i] * b[j]的值大于x,那么往后所有的a[i] * b[j] 都大于x,这显然是不行的,除非指针j回溯到之前的位置。

(2)j从末尾开始出发:因为枚举的a[i]是逐渐增加的,那么每一次指针j停下的位置永远是往前而不可能回溯到之前的位置的。因为a[i]的值是递增的,那么当a[i] * b[j] > x 的时候,b[j]的值要更小,所以j不需要回溯。

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

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];
    
    //j从末尾开始移动
    for(int i = 0, j = m - 1; i < n; i ++ )
    {
        while(a[i] + b[j] > x && j >= 0) j --;
        if(a[i] + b[j] == x)    cout << i << " " << j << endl;
    }

    /*j从头开始移动,错误
    for(int i = 0, j = 0; i < n; i ++ )
    {
        while(a[i] + b[j] < x && j < m)  j ++;
        if(a[i] + b[j] == x)    cout << i << " " << j << endl;
        else j --;
    }
    */

    return 0;
}


2816. 判断子序列 - AcWing题库

#include <iostream>

using namespace std;

const int N = 100010;

int a[N], b[N];

int main()
{
    int n, m;
    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;
    for(i = 0, j = 0; i < n; i ++ ) //i指针指向a,j指针指向b
    {
        while(a[i] != b[j])
        {
            if(j == m)  //如果i还没有走完j就已经走到头了
            {
                cout << "No" << endl;
                return 0;
            }  
            j ++ ;  //不匹配,j前进一位
        }
        j ++;   //匹配,j需要前进一位
    }
    
    cout << "Yes" << endl;
    
    return 0;
}

 注意这种写法会出现 Segmentation Fault   

    for(i = 0, j = 0; i < n; i ++ ) //i指针指向a,j指针指向b
    {
        while(a[i] != b[j])
        {
            j ++ ;  //j前进一位
            if(j == m)  //如果i还没有走完j就已经走到头了
            {
                cout << "No" << endl;
                return 0;
            } 
        }
        j ++;   //相等时j需要前进一位
    }

解释:

相较于AC的代码,区别仅仅在于当a[i]和a[j]不匹配的时候,我们是先前进j在判断j是否到达了终点

在sg的版本中,如果j++之后j=m了,这时候肯定是不匹配的(b[j]=0),while循环继续,此时j=m+1,if判断无法结束,导致无限while循环(i和j永远不匹配,j一直递增直到越界出现sg)。

而如果先判断if再j++的话,j=m的时候就会直接判断出来。

或者将j==m的判断条件改为j>=m即可。所以说,在这种判断是否越界的问题上,最好使用>=而不是==,因为这种细节很容易忽略,在检查时也会浪费很多时间,并且很多题目都会涉及到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

双指针算法模板和应用 的相关文章

随机推荐

  • 旋转框目标检测mmrotate v1.0.0rc1 之RTMDet训练DOTA(二)

    1 模型rotated rtmdet的论文链接与配置文件 注意 我们按照 DOTA 评测服务器的最新指标 原来的 voc 格式 mAP 现在是 mAP50 IN表示ImageNet预训练 COCO表示COCO预训练 与报告不同的是 这里的推
  • 多重背包问题大全(超详细)

    题目 有N种物品和一个容量为V的背包 第i种物品最多有n i 件可用 每件费用是c i 价值是w i 求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量 且价值总和最大 首先多重背包问题可以转换为01背包来解决 关键就是如何转换 我
  • 联合目标检测和语义分割——学习笔记

    联合目标检测和语义分割 目标检测 目标检测是一种与计算机视觉和图像处理相关的计算机技术 用于检测数字图像和视频中特定类别的语义对象 例如人 建筑物或汽车 的实例 然而现实中物体的尺寸 姿态 位置都有很大的差异 甚至还可能出现重叠现象 这使得
  • vue--el-tree懒加载数据并且实现树的过滤

    树的样式 过滤效果 过滤代码实现 1 如果这里的树数据是全加载 即可使用element ui中的设置 进行前端过滤 element ui对应的组件位置
  • 究竟什么是token??

    基于服务器验证方式的验证流程 我们都是知道HTTP协议是无状态的 这种无状态意味着程序需要验证每一次请求 从而辨别客户端的身份 在这之前 程序都是通过在服务端存储的登录信息来辨别请求的 这种方式一般都是通过存储Session来完成 随着We
  • Java并发编程学习10-任务执行与Executor框架

    Java并发编程学习系列 任务执行与Executor框架 任务执行 1 串行地执行任务 2 显式地为任务创建线程 3 无限制创建线程的不足 Executor框架 1 基于 Executor 的 Web 服务器 2 执行策略 3 线程池 4
  • 2019最新 国内唯一的Android从程序员到架构师全套教程

    课程目标 国内唯一的Android从程序员到架构师全套视频教程 适用人群 Android开发至少两年经验的IT工程师 想深入了解Android开源平台的资深工程师 Android项目团队技术管理者 课程概述 遵循敏捷的迭代过程 从思想 方法
  • (二)Rocketmq目录结构及设计目标

    文章目录 一 目录结构 二 设计理念与目标 2 1设计理念 2 2设计目标 一 目录结构 1 broker broker模块 2 client 消息客户端 包含消息生产者 消费者相关类 3 common 公共包 4 dev 开发者信息 非源
  • 如何安装vtk入门篇

    转载 原来写过一些文字 觉得没有用 现在发现很多朋友学习vtk起步很难 自己又把它拿出来 改了改贴出来 同时也帖在自己的blog里 希望对新手有帮助 我这里使用的是vtk5 0 介绍如何安装在windows和linux上 都是我实践过的流程
  • 多项目管理的一点思考

    与人闲聊 被问到如何去同时管理多个软件项目 讨论思考有三 第一 制度化 多个项目进行 势必会分散人的精力 在有限的时间如何把这些工作做好 通过规范化的制度 各个项目的文档 进度都应该做到去规范 制度化 第二 项目进度的掌控 软件项目最重要的
  • 详解 ElasticSearch Kibana 配置部署

    默认安装部署所在机器允许外网 SSH工具 Putty 链接 https pan baidu com s 1b6gumtsjL L64rEsOdhd4A 提取码 lxs9 Winscp 链接 https pan baidu com s 1tD
  • UE4-AI

    AI的三大阶段 AI的处理过程可以分为三大阶段 感知 思考 行动 感知 对AI当前状态作记录 基本过滤 也是一种感知行为 基本过滤 如果其他感知的优先级更高 会忽略部分信息 思考 AI利用感知阶段收集到的信息 对当前信息和目标进行评估 为之
  • kubenetes创建Pod/RC时的一些报错问题解决

    问题1 虽然每次通过yaml创建rc都显示成功了 但是 kubectl get pod却没显示任何的pod 问题2 直接通过yaml创建pod提示apixxx 问题3 通过 json文件创建pod 未验证 原因是身份认证 解决办法 跳过认证
  • 【OpenCV】图像梯度处理

    使用Sobel算子 cv2 Sobel 图像对象 图像深度 水平方向 dx 竖直方向 dy Sobel算子大小 图像深度 通常设为 1 表示输入与输出的图像深度保持一致 水平方向 若选择计算水平方向则设为 1 否则为 0 竖直方向 若选择计
  • 仿动画效果按钮(firemonkey)

    如图所示 放置一个如此的按钮 1 放置roundrectangle1 2 放置floatanimation1 parent设置为roundrectangle1 3 设置floatanimation1属性 4 放置floatanimation
  • 记录分页懒加载功能,数据列表,每次触底实现分页懒加载

    1 引用uview加载更多标签 页面中定义
  • 【Y 新闻】YMatrix携手三一集团,荣获“2023爱分析·数据库最佳实践案例”

    2023 年 8 月 16 日 由爱分析主办的第五届数据智能高峰论坛在北京 JW 万豪酒店成功举办 本次论坛以 激活数据资产 释放数据价值 为主题 聚焦企业在数据能力和数据应用建设过程中所面临的系列问题 会上 由 YMatrix 与三一集团
  • MQTT.fx下载安装与使用

    软件下载 Index of apps mqttfx 1 7 1 https file bemfa com hw zip mqtt mqttfx 1 7 1 windows 64 exe 链接 https pan baidu com s 1j
  • 访问github仓库中的资源

    使用GitHub自己的服务器raw githubusercontent com 参考 https www zhihu com question 35011078 使用方法 https raw githubusercontent com 用户
  • 双指针算法模板和应用

    目录 模板 应用场景 例题 注意这种写法会出现 Segmentation Fault 模板 for int i 0 j 0 i lt n i while j lt i check i j j 具体问题的逻辑 常见问题分类 1 对于一个序列