给定一个含有 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
提示:
1 <= target <= 1091 <= nums.length <= 1051 <= nums[i] <= 105
进阶:
- 如果你已经实现 **
O(n)时间复杂度的解法, 请尝试设计一个O(n log(n))时间复杂度的解法。
题解
暴力的方法是直接两个for循环枚举每一个子数组的和,跟目标数进行比较,结果毫无疑问的超时了。
想到双指针也可以用来遍历每一个子数组,时间上或许可以两个for循环快。
指针分为左指针跟右指针,两者都从0下标出发,一前一后就可以表示出子数组,不过两个指针前进的条件就要进行修改,这点很关键,不然就会超时。
指针前进的条件,对于右指针,如果此时子数组的和比目标数要小,右指针前进,代表在子数组中添加一个数,使它的和变大。对于左指针,如果和比目标数要大或者两者相等的时候前进,代表从这个子数组中去掉一个数,同时因为和已经比目标数大了,此时就可以记录下长度,一直更新这个长度直到循环结束。 代码如下:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left=0,right=0;
int sum=0,mmin=999999999;
while(left<=nums.length-1){
if(sum<target&&right<nums.length){
sum+=nums[right++];
}
else if(sum>=target){
mmin=Math.min(mmin,right-left);
System.out.print(mmin+" ");
sum-=nums[left++];
}
else {
left++;
}
}
if(mmin==999999999)return 0;
return mmin;
}
}
虽然很慢,你就说过没过吧。