LeetCode_209 长度最小的子数组
LeetCode_209 长度最小的子数组
题目要求
给定一个含有
n
** 个正整数的数组和一个正整数target
。**
找出该数组中满足其总和大于等于target
的长度最小的 连续子数组[nums<sub>l</sub>, nums<sub>l+1</sub>, ..., nums<sub>r-1</sub>, nums<sub>r</sub>]
,并返回其长度**。**如果不存在符合条件的子数组,返回 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
提示:
1 <= target <= 10<sup>9</sup>
1 <= nums.length <= 10<sup>5</sup>
1 <= nums[i] <= 10<sup>5</sup>
思路
使用滑动窗口法,双指针slow和fast分别指示窗口的左右边界,首先快指针开始右移,慢指针不动,同时求和sum开始累加,直到碰到sum>=target,开始考虑 最小 子序列的问题,慢指针尝试右移以缩小窗口大小
代码与解析
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {// 初始化慢指针和快指针,分别指向数组的开始位置int slow = 0;int fast = 0;// 初始化当前子数组的和为0int sum = 0;// 初始化最小子数组长度为数组长度加1,这是为了确保最小长度一定小于数组长度int minLength = nums.size() + 1;// 使用快慢指针法遍历数组while(fast < nums.size() && fast >= slow){// 快指针向前移动,将当前元素加入到当前子数组的和中sum += nums[fast];// 当当前子数组的和大于或等于目标值时,开始尝试缩小子数组的长度while(sum >= target && slow <= fast){// 更新最小子数组长度minLength = minLength > (fast - slow + 1) ? (fast - slow + 1) : minLength;// 如果最小长度已经为1,则不需要继续寻找更小的子数组,直接跳出循环if(minLength == 1){break;}// 慢指针向前移动,将当前元素从当前子数组的和中减去sum -= nums[slow];// 慢指针向前移动slow ++;}// 快指针向前移动fast ++;}// 如果最小长度仍然为初始值,说明没有找到满足条件的子数组,返回0// 否则,返回最小子数组长度return (minLength == (nums.size() + 1)) ? 0 : minLength;}
};
方法和思想
- 快慢指针法:使用两个指针,一个快指针用于扩大子数组的范围,一个慢指针用于缩小子数组的范围,以此来找到满足条件的最小子数组。
- 滑动窗口:这种方法实际上是滑动窗口的一种应用,通过调整窗口的大小来找到满足条件的最小窗口。
时间复杂度
- 时间复杂度:O(n),其中 n 是数组的长度。因为每个元素最多被访问两次,一次是快指针扫描,一次是慢指针缩小窗口。
空间复杂度
- 空间复杂度:O(1),因为只使用了几个固定的变量,与输入数组的大小无关。