目录
题目
暴力算法
用两个指针,两层循环,列举出所有的结果,把每次符合的最优结果更新到临时变量里。代码如下
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
// 记录结果
int ret = INT_MAX;
int n = nums.size();
// 枚举出所有满⾜和⼤于等于 target 的⼦数组[start, end]
// 由于是取到最⼩,因此枚举的过程中要尽量让数组的⻓度最⼩
// 枚举开始位置
for (int start = 0; start < n; start++)
{
int sum = 0; // 记录从这个位置开始的连续数组的和
// 寻找结束位置
for (int end = start; end < n; end++)
{
sum += nums[end]; // 将当前位置加上
if (sum >= target) // 当这段区间内的和满⾜条件时
{
// 更新结果,start 开头的最短区间已经找到
ret = min(ret, end - start + 1);
break;
}
}
}
// 返回最后结果
return ret == INT_MAX ? 0 : ret;
}
};
优化
如何做优化呢?题目里说数组里的都是正整数,当区间里已经符合条件了,我们还需要把最右边的指针重置到左边吗
上图中,灰色的区间已经是符合条件的区间了,此时黑色指针向右移动一格,如果是暴力算法,红色指针应该重置到黑色指针的位置,然后向右遍历。我们来讨论一下,红色指针有必要重置吗?显然没有必要的
黑色指针向前移动一个之后此时会有两种情况
1.灰色区间依旧符合条件,红色指针被重置然后遍历,依旧是当前的灰色区间。
2.灰色区间不符合条件,红色指针被重置后遍历,由于整个区间都是正整数,灰色区间的大小只会增加。
也就是说,我们完全没必要再让红色指针遍历一灰色区间了。
那么灰色区间就是滑动窗口算法中的窗口,这道题的算法如下:
1.红色指针右移,数据入窗口
2.判断窗口是否符合条件
3.不符合条件继续让新数据入窗口,符合条件更新最优结果,并且让最左边的数据出窗口
代码如下:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int sum = 0;
int l_ptr = 0;
int r_ptr = 0;
int len = INT_MAX;
while (r_ptr < n) {
sum += nums[r_ptr++];
while (sum >= target) {
len = min(len, r_ptr - l_ptr + 1);
sum -= nums[l_ptr++];
}
}
return len == INT_MAX ? 0 : len - 1;
}
};