于2021.11.26练习
题目链接
1.1 解法1:暴力解法之两次遍历
思路:首先初始化这个子组的最小长度为Integer.MAX_VALUE,然后遍历数组的每一个下标作为子组的第一个元素,对于每一个开始下标i,需要找到大于或等于i的最小下标j,使得从nums[i]到nums[j]这个区间内元素之和大于target。如果找到了大于target,就更新最小长度,同时break操作,意味着j下标不用在往下遍历了,因为这个数组全都是正整数,再往后相加只会越来越大。
我自己写的时候,初始化最小长度为nums.length,然后写到最后return语句,不知道该返回什么了,其实只需要用到一个三目运算符,判断此时的最小长度是否为一开始初始化的最小长度,如果等于,那说明并没有找到大于target的子组,就返回0;如果不等于,那说明最小长度后面做了更新,因此返回更新的最小长度即可。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int minLen = Integer.MAX_VALUE;
for(int i = 0;i < nums.length;i++){
int sum = 0;
for(int j = i;j < nums.length;j++){
sum += nums[j];
if(sum >= target){
minLen = Math.min(minLen,j - i + 1);
break;
}
}
}
return minLen == Integer.MAX_VALUE ? 0 : minLen;
}
}
1.2 解法2:滑动窗口
思路:用left标记滑动窗口的左指针,用i标记滑动窗口的右指针。i是一直都往后移动的,用于扩张窗口。只有当目前窗口中的元素之和大于等于target时,left指针才会往后移动,用于收缩窗口,同时需要更新子数组的长度,同时窗口中元素之和也需要减去上一个left指向的元素。
注意:只有当前窗口中元素之和 大于等于target,就要让left一直移动,因此这个过程需要用while循环实现,而不应该用if实现。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int minLen = Integer.MAX_VALUE;
int sum = 0;
for(int i = 0;i < nums.length;i++){
sum += nums[i];
while(sum >= target){
minLen = Math.min(minLen,i - left + 1);
sum -= nums[left];
left++;
}
}
return minLen == Integer.MAX_VALUE ? 0 : minLen;
}
}