209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 0。
示例:
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
前缀和
求出前缀和,对每个前缀和搜索前面的,直到找到满足差值s的位置,得到其最短距离;
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n=nums.size();
preflx.resize(n+1,0);
int Mlength=INT_MAX;
for(int i=1;i<=n;i++){
preflx[i]=preflx[i-1]+nums[i-1];
for(int j=i-1;j>=0;j--)
if(preflx[i]-preflx[j]>=s){
Mlength=min(Mlength,i-j);
break;
}
}
if(Mlength==INT_MAX) Mlength=0;
return Mlength;
}
private:
vector<int> preflx;
};
解法2:双指针
滑动窗口;
窗口内和大于s,头指针右移,并保存距离;
窗口内和小于s,尾指针右移;
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int Minlength=INT_MAX;
int head=0;
int tail=0;
int sum=0;
int n=nums.size();
while(tail<n)
{
sum+=nums[tail++];
while(sum>=s){
Minlength=min(tail-head,Minlength);
sum-=nums[head++];
}
}
if(Minlength==INT_MAX) Minlength=0;
return Minlength;
}
};
二分法
数组元素均为非负整数,故前缀和为升序序列;
故可使用二分法,在确定一个数的情况下,找到另一个数;
使用lower_bound(begin(),end(),num) 可以更方便的找到想要的数;
复杂度为二分法复杂度logn;
总复杂度为nlogn;
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n=nums.size();
preflx.resize(n+1,0);
int Mlength=INT_MAX;
for(int i=1;i<=n;i++)
preflx[i]=preflx[i-1]+nums[i-1];
for(int i=1;i<=n;i++)
{
int findint=preflx[i-1]+s;
auto t=lower_bound(preflx.begin(),preflx.end(),findint);
if(t!=preflx.end())//找到了t
Mlength=min(Mlength,static_cast<int>(t-(preflx.begin()+i-1)));
}
if(Mlength==INT_MAX) Mlength=0;
return Mlength;
}
private:
vector<int> preflx;
};