LeetCode-209-长度最小的子数组

题目

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

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

示例 1:

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

示例 2:

1
2
输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

1
2
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

进阶:

  • 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

题解

这一题我一开始没注意到需要连续,直接排序然后从后面往前找,超过了返回长度就好了,还感觉秒了,但是题目的要求是需要连续,orz

209. 长度最小的子数组 - 力扣(LeetCode)

学习了一下佬的解法,还是很巧妙的:

首先要求的是连续,也就是滑动窗口,这里我们考虑一个队列,初始队列为空,sum记录当前队列的元素之和,如果sum < s,我们就让元素入队;

当sum >= s的时候,我们先记录下当前最短的队列长度,然后依次出队,直到sum < s,因为队列先进先出,因此能保证连续性;

直到循环结束(从开头到末尾),就可以找到最小的队列长度。

代码实现用的双指针,用来标记滑动的窗口(也就是队列),入队的时候hi++,出队的时候lo++,队列长度自然就是hi - lo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int minSubArrayLen(int s, int[] nums) {
int lo = 0, hi = 0, sum = 0, min = Integer.MAX_VALUE;
while (hi < nums.length) {
sum += nums[hi++];
// 如果sum大于s,要记录最短的下标,然后出栈,直到sum小于s
while (sum >= s) {
min = Math.min(min, hi - lo);
sum -= nums[lo++];
}
}
return min == Integer.MAX_VALUE ? 0 : min;
}
}

LeetCode-209-长度最小的子数组
https://excelius.xyz/leetcode-209-长度最小的子数组/
作者
Ther
发布于
2024年6月23日
许可协议