🍉🍉 今天的博客又来了又来了🍉🍉
1.题目解析
题目是:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组
解析:题目的意思很好理解就是数组中连续的数的和 == target,连续个数最短的集合,很容易理解。
2.解法原理
看到一道题我们大多数人都是先选择使用暴力解法,这是最基本的解法,但是大多数情况只适用简单题,大多数情况 ,暴力解法的复杂度比较高,运行时间过长会导致代码跑超时。
所以这道题,使用暴力枚举的方法很简单,两个for循环可以直接解决:
用图和伪代码来说就是
第一层循环:
第二层循环:
public int minSubArrayLen(int target, int[] nums) {
int len = Integer.MAX_VALUE;//一定要将len的值设置为最大值,因为0和任何数相比都会比他小,题目要求数组都属正数
for(int left = 0;left < nums.length;left++){
//定义第一层循环
int sum = 0;
for(int right = left;right < nums.length;right++){
定义第二层循环
sum +=nums[right];
if(sum >= target){
//判断值是否大于或者等于target
len = Math.min(len,right-left+1);//取最小长度
break;//退出第二层循环
}
}
return len == Integer.MAX_VALUE ? 0 : len;
}
}
优化:
我们想想在进入第二层循环,我们有没有必要将right退回至left处,重新计算sum的值,我们已经计算过一次sum,如果我们将left向前推进一步前,将left所在的位置的值在sum减去,重新判断sum的值是否 > target.是不是就不用将right再返回来,浪费时间复杂度,这样我们只需要遍历一次数组即可解决问题。
红字部分我们需要注意,这里会出现两种种情况 如果新的 sum >= target 即重新计算len,sum<taget,只需要让right++即可。
说到这里终于到我们的重头戏了
滑动窗口:基于单调性,使用 "同向双指针",对窗口进行调整。
Ps:没看错 还是老朋友双指针
一般分为三个步骤:
1.指针1:left = 0,right = 0;
调整窗口
2.进窗口:对于本题来说移动 right
3.判断 :对于本题来说是 sum >= target
更新结果:本题是 对最数组最小长度len进行更新
出窗口 :调整 left.
基于对上面的解释我们可以知道,进入窗口开始我们要一直对left right的位置进行调整,所以需要一个循环,前面咱也说了在判断阶段,我们不清楚更新后的sum有两种情况,如果sum > target,我们要继续对len进行更新,继续对sum的调整,所以这里需要一个循环。
3. 代码演示
public int minSubArrayLen(int target, int[] nums) {
//定义两个指针,并且设置len为最大值,以免为0冲突。
int left = 0,right = 0,n = nums.length,len = Integer.MAX_VALUE,sum = 0;
for(;right < n;right++){
sum += nums[right];//进入窗口
while(sum >= target){//判断
len = Math.min(len,right-left+1);//更新结果
sum -= nums[left++];//更新sum值 并出窗口
}
}
return len == Integer.MAX_VALUE ? 0 : len;//对len进行判断,以免找不到返回的值为最大MAX
}
复杂度分析:
时间复杂度:这里虽然使用了两个while循环,但是判断阶段while循环的循环次数可以忽略不计,从始至终,都是left,right将整个数组进行遍历 ,所以空间复杂度是O(N)。
空间复杂度:从始至终都没有创建数组,使用有限的变量便解决了问题,所以空间复杂度是O(1).
完!!!
觉得本博客不错的记得一定记得一件三连!!! 有错误请指出,一定知错就改!!!!