题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例
- 输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。 - 输入:target = 4, nums = [1,4,4]
输出:1 - 输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提交代码与结果
class Solution {
public int minSubArrayLen(int target, int[] nums) {
for(int i=0;i<target;i++){
for(int j=0;j<nums.length;j++){
//j-i==-1则当前长度i对于数组已经越界最小方向
if((j-i)>=0){
int sum=0;
for(int k=0;k<=i;k++){
sum+=nums[j-k];
}
if(sum>=target)return i+1;
}
//(j+i)==nums.length代表数组在右边已经越界
if((j+i)<=nums.length-1){
int sum=0;
for(int k=0;k<=i;k++){
sum+=nums[j+k];
}
if(sum>=target)return i+1;
}
}
}
return 0;
}
}
结果
学习到的东西
第一次的代码,我个人当时还以为是target^2*n的时间复杂度来着,而且是按照示例给出的数组进行构思来着,没有想到如果target足够大,甚至比nums的长度还要大的时候,算法就退化成O(n^2)了。也确实是个人考虑太简单了。
从大佬那学到的方法为滑动窗口方法,其实也是双指针法,也就是执行起来很像滑动窗口而已。
左右指针分别代表滑动窗口的左右边界,右指针就是for循环内的i,每次循环都会将左右边界内的若干数值进行相加,如果结果满足条件(sum>=target),则会将当前滑动窗口的长度和之前的长度相比较,直至结束才能确定最小的滑动窗口也就是结果数组长度的最小值。继而将窗口的左边界向右移动一位并将左指针指向的值从窗口和中剪掉,再次判断是否满足条件,以此来得到更小的结果数组的长度。
最终得到此题的个人代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left=0;
int sum=0;
int resultLength=Integer.MAX_VALUE;
//滑动窗口
for(int right=0;right<nums.length;right++){
sum+=nums[right];
while(sum>=target){
//求出最小的子序列长度
//计算当前符合条件的子序列长度
resultLength=Math.min(resultLength,right-left+1);
sum-=nums[left++];
}
}
return resultLength==Integer.MAX_VALUE?0:resultLength;
}
}
标签:target,nums,int,resultLength,数组,LeetCode209,长度
From: https://www.cnblogs.com/whitePuPigeon/p/17765685.html