最小子数组:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 子数组
[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3]
是该条件下的长度最小的子数组。
解析:滑动窗口解法
既然叫滑动窗口就得有一个在逻辑上像是窗口的边界的东西,我们定义的这个窗口应该是从左至右进行遍历的
如图,我现在创建了一个窗口将2这个元素包含进去了,此时窗口中元素的值和为2 ,假设target这个目标值为7,此时窗口中的元素和是小于7的,那么我们需要不断的扩大窗口使窗口中的元素和是大于等于7的。
想要在这个数组中找到一个最小的子数组和能大于7的,我们就得先找到一个和能大于7的子数组
此时我们找到了第一个大于等于7的子数组,先将这个结果记录下来,方便之后找到第二个结果时进行比较。此时我们知道窗口中的元素和是大于等于7的但不知道是不是最短的, 所以此时缩小窗口的大小将第一个元素移除,因为我们已经将这个结果记录下来了所以可以移除,此时我们窗口元素和再次小于了7,继续循环上次的操作,直至窗口的右边界到达数组的右端。
经过循环我们已经遍历了所有子数组和能大于等于7的子数组并将它们的长度进行比较,最后得到结果。
下列是c语言实现代码
#define INT_MAX 2147483647
int minSubArrayLen(int target, int* nums, int numsSize) {
int left=0; //定义左指针为数组起始位置
int sum = 0; //定义用于与target比较的变量
int result =INT_MAX;
for(int right=0;right<numsSize;right++){ //用窗口的右边界遍历数组
sum+=nums[right]; //将当前的元素添加到当前子数组的和中
while(sum>=target){ //当当前子数组的和大于等于 target 时,尝试缩小子数组的长度
int length = right-left+1;
if(result>length){
result = length; //记录当前数组长度
}
sum-=nums[left++]; //缩小子数组的长度,左指针右移,并从和中减去左指针指向的元素
}
}
// 如果 result 仍然是 INT_MAX,说明没有找到符合条件的子数组,返回0;否则返回找到的最短子数组的长度
return result == INT_MAX ? 0 : result;
}
以下是c语言完整代码:
#include<stdio.h>
#define INT_MAX 2147483647
int minSubArrayLen(int target, int* nums, int numsSize) {
int left=0; //定义左指针为数组起始位置
int sum = 0; //定义用于与target比较的变量
int result =INT_MAX;
for(int right=0;right<numsSize;right++){ //用窗口的右边界遍历数组
sum+=nums[right]; //将当前的元素添加到当前子数组的和中
while(sum>=target){ //当当前子数组的和大于等于 target 时,尝试缩小子数组的长度
int length = right-left+1;
if(result>length){
result = length; //记录当前数组长度
}
sum-=nums[left++]; //缩小子数组的长度,左指针右移,并从和中减去左指针指向的元素
}
}
// 如果 result 仍然是 INT_MAX,说明没有找到符合条件的子数组,返回0;否则返回找到的最短子数组的长度
return result == INT_MAX ? 0 : result;
}
int main(){
int n,target;
printf("输入数组长度:");
scanf("%d",&n);
printf("输入target:");
scanf("%d",&target);
int arr[n];
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
int result = minSubArrayLen(target,arr,n);
printf("result: %d",result);
return 0;
}
下列是示例:
感谢你看到这里如果代码有误或无法运行请留言