连续子序列的个数(双指针)

题目:

问题描述

给你一个长度为 𝑛n 的数组 𝑎a 和一个数字 𝑚m ,请你计算这个数组有多少个连续子序列的和大于等于 𝑚m ?

如果两个连续子序列来自数组中的不同位置,我们认为它们是不同的,即使它们在内容上是相同的。

输入格式

第一行输入两个整数表示 𝑛n 和 𝑚m 。

第二行输出 𝑛n 个整数表示 𝑎a 数组的元素。

输出格式

输出一个整数表示 𝑎a 数组有多少个连续子序列的和大于等于 𝑚m 。

样例输入

4 10
6 1 2 7

样例输出

2

说明

保证对于所有数据有:1≤𝑛≤105,1≤𝑚≤1010,1≤𝑎[𝑖]≤1051≤n≤105,1≤m≤1010,1≤a[i]≤105 。

代码:

#include <iostream>
using namespace std;
long long m;
const int N=1000010;
int a[N];
int main()
{
  // 请在此输入您的代码
  //窗口滑动,[slow,fast]这个区间的和sum,当满足sum>m时说明快指针从slow到fast+fast之后到n的所有子数组也符合,
  //则此时count=count+n-fast即为slow开始这个位置的连续子序列的个数
  //1,2,3,4,5,6    [slow,fast]=[0-3]=1,2,3,4,sum=10>9   则1,2,3,4,5  1,2,3,4,5,6都符合,所以count=count+6-3
  //因为是连续,所以1,2,3,4,6不可以。所以直接加n-fast5,6即可
  //当这个慢指针开始的都满足完了,窗口在王后移动一个,同时sum减去这个时刻slow所指向的值,slow++慢指针往后移动,fast也往后移动,并在继续求和,当满足sum>m时的值
  //最后输出count即为最终结果
  int n;
  long long sum=0,count=0;
  //注意sum最后是long long型的保险,因为最大sum=100000*100000=1e10超出了整型int的范围
  //count不知道为什么int类型的不行有一个测试样例没通过。最坏的情况第一个数字就>m。则count会有(1+2+3+...+n)=(n*(n+1))/2会有1e10大于int范围了
  cin>>n>>m;
  for(int i=0;i<n;i++){
    cin>>a[i];
  }
  int slow=0,fast=0;
  for(;fast<n;fast++){
    sum+=a[fast];//窗口滑动向后求和
    while((sum>=m)&&slow<=fast){
      count+=(n-fast);//注意加括号,不然就算成了count=count+n了
      sum-=a[slow];//窗口滑动
      slow++;//指针后移
      //for循环后fast自动加一后移
    }
  }
  cout<<count<<endl;
  return 0;
}

注意:

注意count和sum的取值范围可能会为long long 型
快慢双指针,窗口滑动
count=count+(n-fast)//如果[slow,fast]的和满足,则从fast开始后的都会满足

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值