前言
滑动窗口算法是一种用于解决数组或者列表中子数组或者字串问题的方法,通常用于在给定数据上执行连续区间的操作,算法基本思想是维护一个固定大小或不定大小的窗口,通过移动窗口的起始位置和结束位置来遍历整个数据。在每个窗口位置,都可以进行一些判断。
一般算法步骤:
- 初始化窗口的起始和结束位置。
- 将窗口内的元素用于计算或判断。
- 移动窗口的起始和结束位置。
- 重复步骤2和步骤3,直到窗口的结束位置达到数据集的末尾。
题目
代码解析
看这道题,如果用暴力方法的话,可以两层for循环,来寻找满足条件的子数组。时间复杂度n^2。
可以考虑使用同向双指针来优化一下,一个指针来控制前面,一个指针来向后移动。
当子数组大于target的时候才需要统计大小,统计完子数组之和,将字串的头部删除,尾部继续向后移动。比如数组当中2 + 3 + 1 + 2之和才大于7,此时子数组的长度为4,将头部2删除,尾部向后移动,加上4,此时子串和是大于7的,删除头部,直到子数组的和小于7,此时子数组为2 4,尾部后移加上3,子数组和大于7,删除头部,此时子数组就剩4 和 3,也就是我们最终要的答案,最小长度的子数组。
观察每次符合条件的子数组,非常像一个窗口在数组中滑来滑去。因此我们也可以将同向双指针算法称为滑动窗口
class Solution {
public:
int minSubArrayLen(int t, vector<int>& nums) {
queue<int> q;
int n = nums.size();
int sum = 0;
int minq = 0x3f3f3f3f;
// 1. 当队列为空的时候,什么都不管,入队
// 2. 当队列中的数字和大于等于tar的时候,纪律个数并出队到小于tar
for (int i = 0; i < n; i++)
{
if (q.empty())
{
q.push(nums[i]);
sum += nums[i];
}
else
{
if (sum < t)
{
sum += nums[i];
q.push(nums[i]);
}
while (sum >= t)
{
int len = q.size();
minq = min(minq, len);
int tt = q.front();
sum -= tt;
q.pop();
}
}
}
return minq == 0x3f3f3f3f ? 0 : minq;
}
};