记录滑动窗口的题
力扣题目链接: https://leetcode.cn/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
提示:
- 1 <= target <= 109
- 1 <= nums.length <= 105
- 1 <= nums[i] <= 105
解法一 : 暴力解法
两层for循环 看了看数据的范围,不会超时,用暴力的话时间复杂度是O(n2) 空间复杂度是O(1)。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int len = nums.length;
int minLen = 0; // 记录序列长度
int sum = 0; // 记录序列的和的值
int result = 99999999; // 记录最终的结果
for(int i = 0; i<len; i++){
sum = 0; // 每次重新尝试都要将每次的序列和归零
for(int j = i;j<len; j++){
sum+= nums[j]; // 累加和
if(sum >= target){
minLen = j - i + 1; // 数组从0开始的,所以要加1
result = result < minLen ? result : minLen; // 三目运算符,
break; // 找到一个就跳出内层循环,外层循环i++
}
}
}
return result == 99999999 ? 0 : result;// 三目运算符返回结果。
}
}
解法二: 滑动窗口法
滑动窗口,就是我们不断去通过调节子序列的起始位置和终止位置,从而得出我们要想的结果。
时间复杂度是 O(n) 空间复杂度 O(1)
我们要知道窗口的起始位置 和 终止位置 ,以及如何移动起始位置(重点)
- 此题的窗口的是什么?
- 窗口的起始位置何时移动?
此题的窗口就是 子序列的值 >= target,这个范围就是窗口的大小。
窗口的起始位置移动的条件是 ,如果当前累加的的子序列的和的值 大于等于 target了,就要向前移动。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int len = nums.length;
int result = 99999999;
int minLen = 0; // 记录长度
int sum = 0; // 记录子序列的长度
int i = 0;// 滑动窗口的起始位置
for(int j = 0; j < len; j++){
sum += nums[j]; // 累加求和
while(sum >= target){
minLen = j - i + 1; // 子序列长度
result = result < minLen ? result : minLen;
sum -= nums[i++];
// sum -= nums[i]; // 与上面表达的意思一致。
// i++;
// 精髓所在,移动起始位置,本质上就是通过每次的sum减去当前的这个i的值,然后 i再向前移动一位。
}
}
return result == 99999999 ? 0 : result;
}
}