题目:
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
方法一:暴力解法
public int minSubArrayLen(int s,int[] nums){
int n = nums.length;
//子序列之和
int sum =0;
//子序列长度
int subLength =0;
int res = Integer.MAX_VALUE;
for (int i = 0; i <n ; i++) {
//设置子序列起点
sum=0;
for (int j = i; j <n ; j++) {
//设置子序列终点
sum+=nums[j];
if(sum >=s){
//更新子序列长度
subLength = j-i+1;
res = Math.min(res, subLength);
break;//如果找到了最小子数组,跳出设置子序列终点的第二层循环,增加子序列起点继续遍历
}
}
}
//如果res没有被赋值的话,就返回0,说明没有符合条件的子序列
return res == Integer.MAX_VALUE ? 0:res;
}
时间复杂度:O(n^2)
空间复杂度:O(1)
方法二:滑动窗口(双指针)
思路:使用左右指针动态地维护和大于s的最小的子数组
//方法二:滑动窗口(双指针)
public int minSubArrayLen(int s,int[] nums){
//数组长度
int n = nums.length;
//子序列之和
int sum = 0;
//子序列长度
int subLength = 0;
//子序列结果
int result = Integer.MAX_VALUE;
//滑动窗口起始位置
int left =0;
for (int right=0;right<n;right++) {
sum+= nums[right];
while (sum>=s){
subLength = right-left+1;
result = Math.min(result, subLength);
sum-=nums[left++];
}
}
return result==Integer.MAX_VALUE? 0: result;
}
时间复杂度:O(n)
空间复杂度:O(1)
为什么for循环里面嵌套while循环时间复杂度是O(n)?
因为时间复杂度考查的是每一个元素重复出现的次数,在滑动窗口中,元素在进入窗口时出现一次,离开窗口时出现一次。因此每一个元素被操作两次,时间复杂度应该是O(2n),也就是O(n)了。