每日一练:LeeCode-209、长度最小的子数组【滑动窗口+双指针】
- 思路
- 暴⼒解法
- 滑动窗口
本文是力扣 每日一练:LeeCode-209、长度最小的子数组【滑动窗口+双指针】 学习与理解过程,本文仅做学习之用,对本题感兴趣的小伙伴可以出门左拐 LeeCode-209、长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足 其总和大于等于 target
的长度最小的 连续子数组
[numsl, numsl+1, ..., numsr-1, numsr]
。
示例 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^9
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
思路
暴⼒解法
两个for循环
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int subLength=0; //子序列的长度
int sum=0; //和
for(int i=0;i<nums.length;i++){
sum=0;
for(int j=i;j<nums.length;j++){
sum+=nums[j];
if(sum>=target){
subLength=j-i+1;
result = result<subLength?result:subLength;
break;
}
}
}
return result==Integer.MAX_VALUE?0:result;
}
}
时间复杂度:O(n^2)
空间复杂度:O(1)
滑动窗口
参考代码随想录
1、滑动窗口:不断的调节⼦序列的起始位置和终⽌位置,从⽽得出我们要想的结果
-
在暴⼒解法中,是⼀个for循环滑动窗⼝的起始位置,⼀个for循环为滑动窗⼝的终⽌位置,⽤两个for循环 完成了
⼀个不断搜索区间的过程。
-
滑动窗⼝⽤⼀个for循环来完成这个操作,而且一个for只能用在滑动窗口的
终止位置
上,反之若用在 起止位置 上,还是会有两层for循环,那就没意思了
2、实现滑动窗⼝,主要确定如下三点:
-
窗⼝内是什么?
-
如何移动窗⼝的起始位置?
-
如何移动窗⼝的结束位置?
窗⼝就是 满⾜其和 ≥ s 的⻓度最⼩的
连续
⼦数组。窗⼝的起始位置如何移动:如果当前窗⼝的值⼤于s了,窗⼝就要向前移动了(也就是该缩⼩了),往右缩小。
窗⼝的结束位置如何移动:窗⼝的结束位置就是遍历数组的指针,也就是for循环⾥的索引。
解题的关键在于 窗⼝的起始位置如何移动,
滑动窗⼝的精妙之处在于根据当前⼦序列和⼤⼩的情况,不断调节⼦序列的起始位置。从⽽将O(n^2)暴⼒解法降为O(n)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int i=0; //起始位置
int subList; //子序列的长度
int sum=0; //和
for(int j=0;j<nums.length;j++){
sum+=nums[j];
// 注意这⾥使⽤while,每次更新 i(起始位置),并不断⽐较⼦序列是否符合条件
while(sum>=target){ //两个精髓;大于等于都是移动滑动窗口起始位置的标志
subList=j-i+1;
result = result<subList? result: subList;
sum-=nums[i++];
}
}
return result==Integer.MAX_VALUE?0:result;
}
}
时间复杂度:O(n)
空间复杂度:O(1)