「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」
最小的子数组
题目描述
给定一个含有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
解析
暴力分解法:两个for循环,不断地寻找符合条件的子数组
代码
public int minSubArrayLen(int target, int[] nums) {
int sum=0; //定义子数组元素之和
int sublength; //定义子数组的长度
int result=Integer.MAX_VALUE;//定义最终结果
for(int i=0;i<nums.length;i++){ //第一层循环
sum=0; //sum初始化为0
for(int j=i;j<nums.length;j++){//第二层循环
sum+=nums[j]; //先计算当前的子数组之和
if(sum>=target){//当sum>=target时执行{}内操作,否则跳出第二层循环
sublength=j-i+1; //计算子数组的长度
result=result<sublength?result:sublength;//比较当前result和sublength的大小,返回较小值
break;
}
}
}
//如果result没有被赋值的话,就返回0,说明没有符合条件的子数组
return result==Integer.MAX_VALUE?0:result;
}
优化后的算法
双指针法
- 定义两个指针fastIndex和slowIndex,初始时都指向起始位置
- slowIndex指向第一个数组元素,fastIndex依次从左向右进行遍历,计算nums[fastIndex]之和
- 当元素值的和大于或等于正整数target时,slowIndex向右移动一位,fastIndex继续遍历
- 重复此过程,直至元素值小于正整数target退出循环
代码
public int minSubArrayLen(int target, int[] nums) {
int sublength=0;//定义子序列的长度
int fastIndex=0;//定义双指针fastIndedx和slowIndex,初始时都指向起始位置
int slowIndex;
int sum=0;//定义子数组的元素之和,初始化赋值
int result=Integer.MAX_VALUE;//定义最终结果
//slowIndex指向第一个数组元素,fastIndex依次从左向右进行遍历
for(slowIndex=0;fastIndex<nums.length;fastIndex++){
//fastIndex依次从左向右遍历,将此过程中遍历的数组元素值进行相加求和
sum+=nums[fastIndex];
//给定循环条件:当元素值的和大于或等于正整数target时
while(sum>=target){
//求出sublength,因为数组下标是从0开始的,所以要加1
sublength=(fastIndex-slowIndex+1);
//将resulth和sublength作比较,谁的值小取谁的结果
result=result<sublength?result:sublength;
//此时sum>=target时,元素和减去slowIndex指向的元素值
sum-=nums[slowIndex];
//slowIndex向右移动一位
slowIndex++;
}//重复以上过程,直至退出循环
}
return result==Integer.MAX_VALUE?0:result;
}