题目
思路
题目要求找到长度最小的子串,使得字串和大于等于S
既然是要长度最小,那我们就可以从长度为1开始遍历到长度为N
,我们需要遍历
∑
i
=
1
N
i
\sum_{i=1}^{N}{i}
∑i=1Ni次 ,当N非常大的时候耗时会特别长,所以可以稍微优化一下(双指针/尺取法)。
如果是按长度从1到N遍历,那么我们每次都要从子串的头到尾重新计算一次子串和,对此我们可以做出这样的优化:
按数组元素的位置遍历,从第一个元素开始,从长度为1不断修改子串的长度,直到子串和刚好大于等于S,再从第二个元素开始,继续往下遍历
代码
#include <iostream>
#include <vector>
using namespace std;
vector<int> nums; //输入的数字序列
int main() {
int t; // number of test cases
int N, S;
cin >> t;
while (t-- > 0) {
nums.clear();
int temp;
int minLength = 1e5; //满足题意的最小长度
cin >> N >> S;
for (int i = 0; i < N; ++i) {
cin >> temp;
nums.push_back(temp);
}
int i = 0, j = 0, sum = nums[0], length = 1; //用于对数组的遍历
if (nums[0] >= S) {
cout << 1 << endl;
continue;
}
//length用于记录当前子串长度
while (j < N && i <= j) {
if (sum < S) {
j++;
sum += nums[j];
length++;
} else {
if (length < minLength)minLength = length;
sum -= nums[i];
i++;
length--;
}
}
//没有答案则输出0
if (minLength == 100000)cout << 0 << endl;
else cout << minLength << endl;
}
}