给定一个含有 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
解题思路:我看到题目想到了用两个循环来遍历所有的可能
public int minSubArrayLen(int target, int[] nums) {
int count = nums.length;//记录子数组的长度
int sum = 0;
int flag = 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){
count = Math.min(count,j-i+1);
flag = 1;//确定循环中是否有过sum>=target
break;
}
}
}
if(flag == 1){
return count;
}
return 0;//flag==0则表示没有出现过sum>=0,则没有子数组,那么最短子数组的长度为0,所以返回0
}
但是这种方法的时间复杂度太高了导致当遇到长数组时性能不够好
于是去学习了滑动窗口的方法
解题思路2(滑动窗口):设定两个指针(start,end)同时指向数组头,循环开始(条件为当end<nums.length条件为真时持续循环)sum += nums[end],嵌套循环(条件sum>=target为真时持续循环)count与子数组长度(end-start+1)做比较,若是count较小则count=子数组长度,sum减去start这一轮指向指针的元素(sum -= nums[i]) ,而后start指针向右移动一格。若sum<target,则end++而后进行下一轮。
public int minSubArrayLen(int target, int[] nums) {
int count = Integer.MAX_VALUE;
int n = nums.length;
int sum = 0;
if(n == 0){
return 0;
}
int i = 0;//start指针
int j = 0;//end指针
while(j < n){
sum += nums[j];
while(sum >= target){
count = Math.min(count,j-i+1);
sum -= nums[i];
i++;
}
j++;
}
return count == Integer.MAX_VALUE ? 0 : count;
}