上文介绍了数组的双下标对撞。
本文介绍双下标的滑动窗口:
- 左右2个下标组成一个窗口,初始化窗口大小可以为0
- 根据条件,不断地扩大或者缩小窗口
- 右下标增加,扩大窗口
- 左下标增加,缩小窗口
- 不断地计算窗口是否符要求,比较目前最优解和本次最优解,找出最终的最优解
LeetCode 209
来源:力扣(LeetCode)209 Medium
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合
条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
解题思路
- 不断地比较窗口元素的和以及目标数
- 窗口的和较小,右下标向右移动,扩大窗口
- 窗口的和较大,左下标向右移动,缩小窗口
C++
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
// [left, right]表示窗口区间,初始窗口区间长度为0,和为0
int left = 0;
int right = -1;
int sum = 0;
int numsLength = nums.size();
int resultLength = numsLength + 1;
while (left < numsLength) {
// 区间和小于目标值,右下标尝试扩大区间
if (sum < target && right + 1 < numsLength) {
right++;
sum += nums[right];
} else { // 区间和大于目标值或者右下标到头,增加左下标,区间缩小
sum -= nums[left];
left++;
}
// 取较小的结果
if (sum >= target) {
resultLength = min(resultLength, right - left + 1);
}
}
if (resultLength == numsLength + 1) {
return 0;
}
return resultLength;
}
};
Swift
class Solution {
func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
// [left, right]表示窗口区间,初始窗口区间长度为0,和为0
var left = 0
var right = -1
var sum = 0
let numsLength = nums.count
var resultLength = numsLength + 1
while left < numsLength {
// 区间和小于目标值,右下标尝试扩大区间
if (sum < target) && (right + 1 < numsLength) {
right += 1
sum += nums[right]
} else { // 区间和大于目标值或者右下标到头,增加左下标,区间缩小
sum -= nums[left]
left += 1
}
// 取较小的结果
if sum >= target {
resultLength = min(resultLength, (right - left + 1))
}
}
if resultLength == numsLength + 1{
return 0
}
return resultLength
}
}
类似的问题包括LeetCode 3, 438, 76,。
更多解题代码查看GitHub地址:https://github.com/Anzeron/Structure-Algorithm-LeetCode
阅读原文,关注公众号[空与一]