方法一:暴力法,将子数组元素数量num初始化为数组元素+1,用双指针进行遍历,i指针从头到尾遍历数组,每次遍历一个i元素,则从i+1的位置开始移动j指针,直至从i到j的元素之和大于target,再判断元素数量是否小于num,若小于则将其赋给num。但执行之后超时
int minSubArrayLen(int target, int* nums, int numsSize){
int i=0;
int j;
int num=numsSize+1;
int temp_sum;
int temp_num=0;
while(i<numsSize){
if(nums[i]>=target){
num=1;
break;
}
j=i+1;
temp_sum=nums[i];
while(j<numsSize){
temp_sum+=nums[j];
if(temp_sum<target) j++;
else{
temp_num=j-i+1;
if(temp_num<num) num=temp_num;
break;
}
}
i++;
}
if(num>numsSize)return 0;
else return num;
}
方法二:双指针法,跟一类似,将子数组元素数量num初始化为数组元素+1,用双指针进行遍历。
但第二层while循环我用了一系列if语句代替,使得每次执行到最外层while的时候不需要让j重新回溯到i+1的位置,而是令i+1
(话说我想起了当时学408时的next数组,感觉上好像这么说起来挺相似的,不过当时没具体去研究代码哈哈)
按以下思考的顺序结合代码可能比较好理解:
第一步:如果有一个数大于或等于target,就不用执行剩余语句了,直接break后返回1
第二步:将当轮j的元素加入temp_sum中,并让j移到下一位元素
第三步:判断上一轮循环形成的temp_sum是否大于或等于target,如是则接着判断temp_num(即i和j之间的元素数量)是否小于num,如是则更新num的值,同时如果i小于j,则将temp_sum减去i对应的元素,并将i指针移到下一元素,此时的temp_sum即为新i到j之间元素的和
第四步:由于子数组元素数量num在最开始初始化为数组元素+1,所以进行判断,如果num>numsSize(其实就是判断num==numsSize,写成这样也一样),说明整个数组加起来不够target,故返回0,否则直接返回num
注意:每轮的i到j区间为左闭右开,因为j是将自身的值加到temp_sum后进行的自增,新j的值并没有在当轮加到temp_sum之中,而是等到下一轮进行判断之后才加进去,因此求temp_num(即i和j之间的元素数量)时不用“j-i+1”,直接“j-i”即可
int minSubArrayLen(int target, int* nums, int numsSize){
int i=0;
int j=i+1;
int num=numsSize+1;
int temp_sum=nums[i];
int temp_num=0;
while(i<numsSize){
//以下为第一步
if(nums[i]>=target){
num=1;
break;
}
//以下为第三步
else if(temp_sum>=target){
temp_num=j-i;
if(temp_num<num) num=temp_num;
if(i<j){
temp_sum-=nums[i];
i++;
}
}
//以下为第二步
else if(j<numsSize){
temp_sum+=nums[j];
j++;
}
else{
break;
}
}
//以下为第四步
if(num>numsSize)
return 0;
else
return num;
}