209. 长度最小的子数组(LeetCode)
题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
- 进阶
如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。
条件分析
- 要求长度最小;
- 数组是连续子数组
解题思路(滑动窗口)
- 定义连续子数组的下标分别为i和j,则如果存在解,则解的值为j-i+1,并记录长度;
- 如果和大于target,记录当前长度,与之前长度相比取最小值,且i需要增加(缩小范围),否则j需要增加(增大范围);
- 如果j已经遍历到了末尾,则等待i增加来缩小范围,如果缩小范围发现小于target,此时j无法增大,说明范围内已经没有解,此时退出循环,因此可以得到循环退出的条件为j<nums.length
编码如下
public int minSubArrayLen(int target, int[] nums) {
int i = 0; // [i,j]保存最小连续子数组
int j = -1; // 初始范围内没有解
int min = nums.length + 1;// 定义一个最小的长度值为不可能的值,即数组的长度+1
int sum = 0;
while (j<nums.length) {
if (sum >= target) {
min = min(min, j-i+1);
sum -= nums[i];
i++;
} else {
j++;
if (j < nums.length) {
sum += nums[j];
}
}
}
if (min == nums.length + 1) { // 此时最小值还是初始值,说明没有解
min = 0;
}
return min;
}
private int min(int min, int newMin) {
if (newMin < min) {
min = newMin;
}
return min;
}
浙公网安备 33010602011771号