问题描述:给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
第一种做法:暴力法
时间复杂度:O(n²)
使用双层for循环,不断的找满足条件的子序列.
public int minSubArrayLen(int target, int[] nums) {
int length =0;//用来定义子数组长度
int sum=0;
int min = Integer.MAX_VALUE;//长度最小,初值为无穷大
for(int i = 0;i<nums.length;i++){
sum = 0;
for(int j =i;j<nums.length;j++){
sum = sum+nums[j];//进行累加
if(sum >= target){//当满足条件后,将此时的子数组长度赋给length
length = (j-i)+1;
if(length<min){//如果这个长度小于min,则更新min
min = length;
}
break;//一旦找到就break
}
}
}
if(min==Integer.MAX_VALUE){//如果min还是初值,则证明没有找到符合条件的子数组,则返回0
return 0;
}
return min;//否则返回min
}
第二种做法:滑动窗口(推荐使用)
时间复杂度:O(n)
思路:
从末尾位置开始叠加,先找到一个满足条件的,然后从起始位置开始缩减,继续找满足条件的
-
第一步:定义起始位置left,滑动窗口和sum,子数组最小长度min,for循环(int right=0)进行循环
-
第二步:sum>=target时,将min进行更新,并且对sum进行缩减,left++查看是否继续满足条件,若不满足,则跳出循环继续寻找下一个符合要求的
代码:
public int minSubArrayLen(int target, int[] nums) {
int left = 0;//起始位置
int sum = 0;//滑动窗口的和
int min = Integer.MAX_VALUE;//最小长度
for(int right = 0;right<nums.length;right++){
sum += nums[right];
while(sum>= target){
min = (right-left+1)<min?right-left+1:min;
sum=sum-nums[left];
left++;
}
}
return min=min!= Integer.MAX_VALUE?min:0;
}