抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。


思路

  • 双指针,一个起点,一个末点,不必要的遍历次数较多
  • 滑动窗口,当不满足条件时,end前进,扩大窗口;当满足条件后,start前进,缩小窗口,找到最小长度

学习点

  • 第一次考虑滑动窗口的时候,思路是窗口长度定长,每次循环根据窗口长度,这样复杂度较高
  • 动态长度的滑动窗口,满足条件后缩小窗口长度,减少很多遍历次数
  • 原理就是,当满足条件后,以 start 开头的满足条件的子数组最小的必是这个数组,因此可以不需要比较之后的以 start 开头的子数组,所以移动 start 指针
  • 实现滑动窗口,主要确定如下三点:
    • 窗口内是什么?
    • 如何移动窗口的起始位置?
    • 如何移动窗口的结束位置?

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 暴力解法
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int minLen = n;
bool found = false;
// 快慢指针
for (int slow = 0; slow < n; slow++)
{
int currSum = 0;
for (int fast = slow; fast < n; fast++)
{
currSum += nums[fast];
// 找到了
if (currSum >= target)
{
found = true;
if (minLen > (fast - slow + 1))
minLen = fast - slow + 1;
}
}
}

return (found ? minLen : 0);
}
};

update:滑动窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 滑动窗口
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
// move window
int n = nums.size();
int minLen = n;
int start = 0;
int end = 0;
int sum = 0;
bool found = false;
while (end < n && start <= end)
{
sum += nums[end];
// 不满足条件,end前进
if (sum < target)
{
end++;
}
// 满足条件,start前进,为了找到最小长度
else
{
found = true;
// 若更小,update minLen
if ((end - start + 1) < minLen)
minLen = end - start + 1;
sum -= nums[start] + nums[end];
start++;
}
}

return (found ? minLen : 0);
}
};