- 题目简述:
- 给定 N 个正整数序列(10 < N < 100 000),每个正整数小于或等于 10000,并给出一个正整数 S(S < 100 000 000)。编写一个程序来查找序列中连续元素的子序列的最小长度,其总和大于或等于 S。
意思就是在一个数列中 找到一个最短的连续子序列,使其Sn恰好是大于给定的S的
- 那么我们可以采用双指针的方法
- 左指针l 用作for循环中 一次往右移动一下
- 右指针r 在while循环中:while(r <= n && sum < s)
- 这两个指针的移动形似蚯蚓
- 每一次for循环都要更新minlen和当前和sum的值
有两个注意的点:
- 由于题目输入的t可能大于1 所以新的轮次开始前要清空数组 memset(a,0,sizeof(a))
- minlen更新是if(sum >= s)的情况下才更新,不然循环跳出来有可能是r > n了,但sum并没有>s
using namespace std;
int a[100010];
int main()
{
int t;
scanf("%d",&t);
while(t--) //循环a次
{
int n,s;
scanf("%d%d",&n,&s);
memset(a,0,sizeof(a));
for(int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
}
int sum = 0, r = 0; //r为右指针 l为左指针
int minlen = n+1; //minlen的初始化值要总数n都大
for(int l = 1; l <= n; l++)
{
while(r <= n && sum < s)
{
r++; //r指针不断右移
sum += a[r];
}
// cout<<l<<" "<<r<<" "<<sum<<endl;
//while循环结束后 r所处的位置就是我们本次循环找到的临界位置
if(sum >= s) //当sum大于s时 才更新minlen
minlen = min(minlen, r-l+1);
//当左指针l向右移动一位时 相应的sum就要减去这个数值
sum -= a[l];
}
if(minlen > n) cout<<0<<endl;
cout<<minlen<<endl;
}
}