首页 > 编程语言 >(坚持每天写算法)算法复习与学习part1基础算法part1-12——双指针算法

(坚持每天写算法)算法复习与学习part1基础算法part1-12——双指针算法

时间:2024-01-27 16:57:32浏览次数:37  
标签:12 int ++ while part1 算法 数组 include 指针

  双指针是一种思路,很多题都可能用得到,这里我就只选取Acwing网站的三道题(事实上我最近就是在这里刷题,leetcode反而不怎么去了,刷完这个网站的我就会去leetcode刷了)

  双指针一般来讲会在数组有序的情况下应用,但是如果是无序的也是有可能的,两个指针会遍历整个数组(如果条件允许的话)。

  我觉得双指针有两种情况,我不知道别人是怎么分类的,我感觉我做过几种题目,一种是两个索引(指针的意思就是索引,并不一定要是数据类型的那个指针),一个在前一个在后,一个往后走一个往前走,根据条件移动直到两个指针相遇,这一种的两个指针目的就是遍历完整个数组。另一种是两个索引,但是两个都是在前面,一个先走另一个根据条件追上去,两指针相遇或者一个到了数组结尾就结束,这一种的数组可以是无序的,并且这一种的主要目的很有可能就是两个指针之间的区间。其他的就是多个数组形成了多指针这种类似的变种了(有新情况我就更新一下)

  那么直接上题目。

1                                           .

   思路:观察题目,题目一开始并没有说是有序的数组,那么直接当成无序的数组来看。题目的意思是找到不重复的数的连续区间,也就是说,我们在找的过程中我们的区间长度都是变动的,数组两端中间的数值不允许重复。其实从这里就可以确定是双指针了,因为双指针就是动态变化的,根据我分的第二类来看,另一个指针就是根据条件来看要不要移动,而这一个条件其实就是某一个数是否重复了。对于某一个数是否重复了,我们可以新建一个数组u,如果重复了那么设定成true,当然这一种我一般是在递归树题目才会使用,双指针的话可以新建一个频率数组,至于怎么用,看代码就可以理解了。

  这里是图解,感谢大佬画的图解:

   这里是代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
//按照示例来做 , 要选择的区间是[i,j],i从0开始循环到n,j从0开始,j不一定循环到n
//而是循环到重复的数的最后一个数(2,2,3,2,j指到第三个2就行),一旦j移动,那么
//区间的s也要删掉,如果不删掉的话while检查条件无法成立,而且题目要求是连续的序列
//j之后不会被赋值为0

//双循环改良,使用while来替代后循环,去掉一些不符合最终条件的数

//关于一些双指针,Bug-Tree大佬有笔记

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


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]] ++;//判断是否有重复数字的数组
        while(s[a[i]] > 1) {
            s[a[j]] --;
            j ++ ;
        }
        res = max(res , i - j + 1);//i - j + 1 是因为左闭右闭(建议回想下前缀和的区间),j
        //
    }

    cout << res;

    return 0;

}

   我们观察一下这个代码,其实双指针是有模板的(嗯,我觉得有就是有),我理解的模板:1.for循环,遍历数组。2.while过滤,while是核心代码。3.if条件,有时候有有时候没有,用来减少无意义代码或者是别的用途,按照题目来讲。我在第一道题的代码的注释里面也有提到在这个模板

  我们来看第二道题目

2. 

                                     

  思路:很容易看出来是遍历数组来找到符合条件的,因为有多个数组,所以很容易想到双指针(哈哈),这一种做出来肯定很容易,难的是时间限制了吧,我们必须尽可能想到如何过滤掉一些没用的,嗯,就是if条件了,回想一下双指针的模板,以下是代码:

  代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 100010;
//观察了一下,这道题用双指针改良,其实就是我想的那样,在里面添加条件就可以了,我看了下题解,就是从后面往前,j还是要经过整个数组
//其实不太符合我内心对双指针的想法。
//
//总结:判断条件是否要进去操作(以减少操作数据规模)和while过滤是双指针的核心
//双指针和双层循环,使用双层循环时候(如果该代码是核心代码的话)可以考虑可不可以使用双指针删掉可能存在的一些无意义
int n , m , x;
int a[N];
int 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++){
        while(j >= 0 && a[i] + b[j] > x) j--;
        if(j >= 0 && a[i] + b[j] == x) cout << i << " " << j << endl;
    }
    
    return 0;
}

  也是for+while+if。那么直接来看第三道题目吧

  第三道题目

3.

   思路:这一道题目明显就是要按照有序的数组来看,因为子序列的要求就是这样子的(),这一道题的思路就是两个数组两个指针,A数组的指针是遍历用的,按顺序遍历到A数组的尾部的过程中如果有和B数组一样的元素那么B数组的指标就会移动,如果A数组遍历完了B数组指针还没到尾部那么B数组就不是A数组的序列。因为是双指针我们直接看模板就可以了。

  这里是代码:

//过早总结了,还有一题,同样需要过滤的while和操作的if条件
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 100010;

int n,m;
int a[N];
int 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 t = n;//t是a数组还没有被匹配的数量

    for(int i = 0 , j = 0 ; i < n; i ++){
        while(a[i] != b[j] && j < m ) j ++; //while进行过滤
        if(j >= m) break;//过滤的时候发现j已经到头了那么就直接break吧,这一步容易没有考虑到
         //匹配状态,其实暗藏着一个if条件a[i] == b[j] ,这是我们操作的条件
            t --; 
            j ++;//匹配到了那么就下一个
    }
    //数量为0则全部匹配成功,不为0就说明b数组按照a数组匹配还没有匹配完b数组就没了,那么结束
    if(t > 0) cout << "No";
    else cout << "Yes";

    return 0;
}

 

标签:12,int,++,while,part1,算法,数组,include,指针
From: https://www.cnblogs.com/clina/p/17991506

相关文章

  • 文本分类识别Python+卷积神经网络算法+TensorFlow模型训练+Django可视化界面
    一、介绍文本分类系统,使用Python作为主要开发语言,通过选取的中文文本数据集("体育类","财经类","房产类","家居类","教育类","科技类","时尚类","时政类","游戏类","娱乐类"),基于TensorFlow搭建CNN卷积神经网络算法模型,并进行多轮迭代训练最后得到一个识......
  • STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写
    1、准备材料正点原子stm32f407探索者开发板V2.4STM32CubeMX软件(Version6.10.0)keilµVision5IDE(MDK-Arm)ST-LINK/V2驱动野火DAP仿真器XCOMV2.6串口助手2、实验目标使用STM32CubeMX软件配置STM32F407开发板使用FatFs中间件通过SPI通信协议对W25Q128芯片进行读写等操作3......
  • Dijkstra算法
    \(Dijkstra\algorithm\)\(Principle\)以点为研究对象的贪心策略,和\(Prim\)类似。\(Implementation\step\)将起点标记;找条连接被标记的点集合中一点和没有被标记的点集合中一点最短的边;将该边连接的没有被标记的点加入被标记的点;将该新加入的被标记的点和它的所有邻接点......
  • 链表算法
    目录链表算法初始化节点1.删除链表的第N个节点2.删除链表中倒数第N个节点3.分块反转链表(K个一组翻转链表)4.反转链表I5.反转链表II(给定区间反转)6.判断是否为环形链表7.两数相加(两个链表相同位置相加)8.合并两个有序链表9.删除排序链表中的重复元素II10.旋转链表(将链表每个节......
  • SQL Server 2012 版本后的自带分页语法
    SQLServer2012与之前版本相比,增加了好多实用性的功能,在之前,数据表中的记录较多,需要分页时,算法比较麻烦,2012版本之后,增加了优雅分页语法,可通过简单的语法实现分页:Select*FromTb_tableOrderBy<排序列>OffSet<起始位置>ROWSFetchNext<返回的行数>RowsOnly说明:1、<......
  • 位运算在算法中的应用
    快速幂问题:给定整数\(a,\b,\p\)计算\(a^b\modp\)\((1\lea,b,p\le10^9)\)分析:我们可以将\(b\)转换成二进制:\[b=c_02^0+c_12^1+c_22^2+...+c_{k-1}2^{k-1}\]其中\(c_n\)的取值为\(0\)或者\(1\)那么有:\[a^b=a^{c_02^0+c_12^1+c_22^2+...+c_{k-1}2^{k-1......
  • 牛客练习赛121
    牛客练习赛121出题人题解|牛客练习赛121题解小念吹气球解题思路:字符长度加字符种类数。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128_t;voidso......
  • 如何学习算法:什么时完全二叉树?完全二叉树有什么特点?
    完全二叉树我们知道树是一种非线性数据结构。它对儿童数量没有限制。二叉树有一个限制,因为树的任何节点最多有两个子节点:左子节点和右子节点。什么是完全二叉树?完全二叉树是一种特殊类型的二叉树,其中树的所有级别都被完全填充,除了最低级别的节点从尽可能左侧填充之外。完全二叉树的......
  • Java学习日记 Day12 心累~
    SpringMVC:主要学了SpringMVC架构下请求与响应的各种方式,在响应中要知道请求转发和重定向的区别。算法:合并二叉树:判断当前节点两棵树的数值关系,然后递归判断左右子树的关系。二叉搜索树中的搜索:根据二叉搜索树的特点,递归查找左右子树,当值相等就返回。验证二叉搜索树:为自己的左......
  • nodejs雪花ID算法(SnowflakeID)
    前言项目中常使用的三种id类型,分别是自增id、uuid、雪花id,这三种各有优劣。本篇主要实现nodejs中snowflake算法的代码。一、Snowflake实现这里需要加入big-integer的模块,下载npminstall--save big-integervarSnowflake=(function(){functionSnowflake(_......