蓝桥杯每日一题 (双指针)

3768. 字符串删减

while循环的双指针,只要遇到一个x,就让y向前探索。不是就加加。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//3768. 字符串删减
char s[110];
int n;
int cnt=0;
int sum=0;
int main()
{
   cin>>n;
   cin>>s;
   int x=0,y=0;
   while(y<n)
   {
       if(s[x]=='x')
       {
           y=x;
           cnt=0;
           while(y<n&&s[y]=='x')
           {
               cnt++;
               y++;
           }
           if(cnt>=3)sum+=(cnt-2);
           x=y+1;
       }
       else
       {
           x++,y=x;
       }
   }
   cout<<sum<<endl;
}

799 最长连续不重复子序列

使用set存储,最初的时候,每次更新ans都是用set的size-1,但是这落下了一种情况,while结束的条件一种是y遇到了set中重复的数,一种是y到头了,所以用y-x去更新值。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//799 最长连续不重复子序列
const int N=1e5+10;
int a[N];
int n;
int ans=1;
unordered_set<int> se;
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    int x=0,y=0;
    while(y<n)
    {
        //无y
        if(!se.count(a[y]))
        {
            while(!se.count(a[y])&&y<n)
           {
               se.insert(a[y++]);
           }
           ans=max(ans,y-x);
        }
        //有y
        else
        {
            while(se.count(a[y]))
           {
               se.erase(a[x++]);
           }
        }
    }
    cout<<ans<<endl;
}

800 数组元素的目标和

能用双指针不仅仅是求最长序列这种情况。

本质应该是利用数据本身的特点用双指针实现一些不必要的迭代。

最开始也想到了利用有序这个特点,但是没想出来。'

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//800  数组元素的目标和
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 j=0;j<m;j++)cin>>b[j];
    //类似剪枝
    for(int i=0,j=m-1;i<n;i++)
    {
        while(b[j]+a[i]>x&&j>=0)
        {
            j--;
        }
        if(b[j]+a[i]==x)
        {
            cout<<i<<" "<<j<<endl;
            return 0;
        }
    }
}

2816. 判断子序列

开始输入写错了

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//2816 判断子序列
const int N=1e5+10;
int a[N],b[N];
int n,m,x;

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int j=0;j<m;j++)cin>>b[j];
    //判断a是否是b的子序列
    int i=0,j=0;
    while(j<m)
    {
        //匹配ij都往后走,
        if(b[j]==a[i])
        {
            j++,i++;
            if(i==n)
            {
                cout<<"Yes";
                return 0;
            }
        }
        else
        {
            j++;
        }
        //到头了

    }
    //如果是因为j到头了
    if(j==m)
        puts("No");

}

1238日志统计

只要存在某个固定长度的子串某个id的点赞数超过某个数,就是热门。

最初的做法是只是 找了所有不重合区间的情况。少了很多情况。

可以存储多个元素的set : multiset

当你需要删除某个数(不重复删除)

cpp 复制代码
 auto it=se.find(rang[i].id);
      se.erase(it);
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//1238 日志统计(超时做法)
const int N=1e5+10;
int n,d,k;
multiset<int>se;//存某个区间某个id出现的次数
map<int,int> mp;//存在几个区间符合要求
struct Range
{
    int ts,id;
    bool operator<(const Range &W)
    {
        return ts<W.ts;
    }
}rang[N];
int main()
{
   cin>>n>>d>>k;
   for(int i=0;i<n;i++)
   {
       int t,id;
       cin>>t>>id;
       rang[i]={t,id};
   }
   sort(rang,rang+n);

   int i=0,j=0;
   while(i<n)
   {
       //走一个区间
      while(rang[j].ts<rang[i].ts+d&&j<n)
      {
        //记录走到的某个点赞记录
         int t=rang[j].id;
         j++;
         se.insert(t);
         //如果符合条件
         if(se.count(t)>=k)
         {
            mp[t]++;

         }
      }
      //i向前走一步,i号记录在set中的id要减少一个
      auto it=se.find(rang[i].id);
      se.erase(it);
      i++;
   }
   for(auto t=mp.begin();t!=mp.end();t++)
   {

        if(t->second)
          cout<<t->first<<endl;
   }

}

y做法:直接用cnt数组动态存储区间中id的个数,只要j离i太远了,就去减去。

1240 完全二叉树的权值

最初自己的做法是从第二行开始判断,也就是i从1开始遍历,i*2只要没越界就用j从i*2+1开始遍历。一个点老是过不了。

最后采用y做法,从第一行开始遍历,j< i+(1 < <(lay -1))为边界

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//1240 完全二叉树的权值
const int N=1e5+10,INF=1e18+10;
int n;
int a[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    long long m=-1*INF,idx,lay=1;
    for(int i=1;i<=n;i*=2)
    {
        long long  sum=0;
        int j=i;
        while(j<i+(1<<lay-1)&&j<=n)
        {
            sum+=a[j];
            j++;
        }
       
        if(sum>m)
        {
            m=sum;
            idx=lay;
        }
         lay++;
    }
    cout<<idx<<endl;

}
相关推荐
煤泥做不到的!34 分钟前
挑战一个月基本掌握C++(第十一天)进阶文件,异常处理,动态内存
开发语言·c++
F-2H37 分钟前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
axxy20001 小时前
leetcode之hot100---24两两交换链表中的节点(C++)
c++·leetcode·链表
chenziang11 小时前
leetcode hot100 环形链表2
算法·leetcode·链表
若亦_Royi2 小时前
C++ 的大括号的用法合集
开发语言·c++
Captain823Jack3 小时前
nlp新词发现——浅析 TF·IDF
人工智能·python·深度学习·神经网络·算法·自然语言处理
Captain823Jack3 小时前
w04_nlp大模型训练·中文分词
人工智能·python·深度学习·神经网络·算法·自然语言处理·中文分词
是小胡嘛4 小时前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_748255024 小时前
前端常用算法集合
前端·算法
呆呆的猫4 小时前
【LeetCode】227、基本计算器 II
算法·leetcode·职场和发展