一、这是一个时间复杂度O(n)的算法。
利用每次遍历一个元素时,如果当前的sum>=target,就会从i到j的范围内找一个更小的子序列,这个子序列的末尾是nums[j],判断这个子序列的和是否满足sum>=target,因为i始终不会超过当前的j,所以降低了时间复杂度,最差情况下,i和j都遍历n次,即2*n,所以是O(n)时间复杂度。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result=100001, subLen=0;
int i=0, j=0, sum=0;
for(; j<nums.length; j++){
sum+=nums[j];
while(sum>=target){
subLen=j-i+1;
result=Math.min(result,subLen);
sum-=nums[i++];
}
}
return result==100001 ? 0:result;
}
}
题目还要求实现O(nlogn)时间复杂度的算法
先说一下暴力搜索的算法,分别遍历每个元素并且以当前遍历的元素开始逐个遍历剩下的元素,所以时间复杂度是O(n^2)。所以改进的搜索方法是使用二分搜索。
说一下前缀和:其中 sums[i]表示从 nums[0] 到 nums[i−1] 的元素和。
题目要求的是最小长度子数组之和大于等于target,所以利用target<=sums[j]-sums[i],得到最小的数组长度是j-i。
这里有个地方得讲明白:如果index<0,说明前缀和数组中没有这个查找的值,所以二分查找返回的是负数,需要转成整数然后加1,得到的结果是前缀和数组中比s大的值所在的下标。所以在之后要判断index<=len是否成立。防止index越界。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int len=nums.length;
int result=100001;
int[] sums=new int[len+1];
for(int i=1; i<=len; i++){
sums[i]=sums[i-1]+nums[i-1];
}
for(int i=0; i<=len; i++){
int s=target+sums[i];
int index=Arrays.binarySearch(sums,s);
if(index<0){
index=-index-1;
}
if(index<=len){
result=Math.min(result, index-i);
}
}
return result==100001? 0: result;
}
}