原题链接
题目不再描述了。
方法: 尺取法(追逐法)
a 为 正数 数组
设子序列
左端点为 i
右端点为 j
sum 为 子序列 的 和。
{
如果 sum 大于等于 s,
i 右移 sum 更新(sum 变小);
如果 sum 小于 s,
j 右移 sum 更新(sum 变大);
}
不断循环此过程 即可。
具体 C语言代码 如下(用 C++ 提交 )
#include<stdio.h>
int main(){
int N, n, s;
int a[100000];
scanf("%d", &N);
while(N--){
int sum = 0, i, j;
scanf("%d%d", &n, &s);
int len = n; //len 为 最短子序列 的长度 假设存在 初始化为n (便于更新)
for(i = 0; i < n; i++){
scanf("%d", &a[i]);
sum += a[i]; //sum 为 数组累加和
}
if(sum < s) printf("0\n"); // 特殊情况 不存在 子序列
else {
i = 0;
j = 0; // 左右端点 的 初始化
sum = a[0]; // sum为 当前子序列的 长度
while( 1 ){
if(sum >= s) {
len = len < (j - i +1) ? len : (j - i + 1); // len 始终记录 最短子序列 的 长度
if(len == 1) break; //最短子序列长度 最小为 1 len为1 直接结束循环
sum -= a[i]; // sum 更新
i++; // 左端点 右移
if( i > n-1) break; // i 超界 结束循环
}
else {
j++; // 右端点 右移
if(j > n-1) break; // j 超界 结束循环
sum += a[j]; // sum 更新
}
}
printf("%d\n", len); // 打印结果
}
}
}