力扣数组基础之双指针长度最小的子数组

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

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

示例

1
2
3
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组

思路

滑动窗口问题主要确定以下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

本题中,窗口就是满足与其和≥s的长度最小的连续子数组

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,窗口的起始位置设置为数组的起始位置就可以了。

滑动窗口的精髓就是根据当前子序列和大小的情况,不断调节子序列的起始位置,从而降低复杂度到O(n).

代码

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
func min(a, b int) int {
if a <= b {
return a
}
return b
}
// 滑动窗口
func minSubArrayLen(target int, nums []int) int {
var result = len(nums) + 1
var sum = 0 // 滑动窗口数值之和
var i = 0 // 滑动窗口起始位置
var subLength = 0 // 滑动窗口的长度
for j := 0; j < len(nums); j++ {
sum += nums[j]
for target <= sum { // 直到target大于和
subLength = (j - i + 1) // 子序列长度
result = min(result, subLength) // 取子序列长度和result最小值
sum -= num[i++] // 滑动窗口不断收缩
}
}
if result == len(nums) + 1{ // 此种情况下没有符合条件的子序列
return 0
}
return result
}