给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出: 2 解释: 子数组[4,3]
是该条件下的长度最小的连续子数组。
进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
方法一:蛮力法
int solve(int a[],int n,int s)
{//暴力破解法,枚举所有子数组
int i,j,sum;
int minlen = n+1;
for(i=0;i<n;i++)
{
sum=0;
for(int j=i;j<n;j++)
{
sum+=a[j];
if(sum>=s)
{
minlen = minlen>(j-i+1)?(j-i+1):minlen;
}
}
}
if(minlen==n+1)
return 0;
return minlen;
}
方法二:指针对撞法,设置快慢指针
要求是连续子数组,所以我们必须定义 i,j两个指针,i 向前遍历,j 向后遍历,相当与一个滑块,这样所有的子数组都会在 [i...j] 中出现,如果 nums[i..j] 的和小于目标值 s,那么j向后移一位,再次比较,直到大于目标值 s 之后,i 向前移动一位,缩小数组的长度。遍历到i到数组的最末端,就算结束了,如果不存在符合条件的就返回 0。
当sum小于正数s时,快指针向右遍历,加上当前数;sum大于s时,舍去慢指针(左边)所指元素,直到慢指针达到数组右端。
#include<stdio.h>
int solve2(int a[],int n,int s)
{
int i=0,j=-1; //滑动窗口
int sum=0,minlen=n+1;
while(i<n)
{
if(sum<s&&j<n)
{
sum+=a[++j];
}
else
{
sum-=a[i++];
}
if(sum>=s)
minlen = (j-i+1)<minlen?(j-i+1):minlen;
}
return minlen==n+1?0:minlen;
}
int main()
{
int a[]={2,3,1,2,4,3},s=7;
int minlen = solve2(a,6,s);
printf("%d\n",minlen);
return 0;
}