【LeetCode每日一题】长度最小的子数组

 
标签:
二分,前缀和,滑动窗口,双指针
- 前缀和&二分
target要大于等于子数组nums[l]到nums[r]这段连续区间的和,因此想到用前缀和sums[r]-sums[l-1]可以快速求得区间和。
如何寻找target呢,要寻找sums[r]-sums[l-1]>=target,移项得sums[r]>=target+sums[l-1],也就是在数组中寻找sums[r]这样得数,使他大于等于target+sum[l-1]。
如何快速查找,因为前缀和数组是递增数组,可以使用二分查找
class Solution {
public:
    int binary_serach(int t,int l,int r,vector<int>&sums)
    {   int mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(sums[mid]>=t)r=mid-1;
            else l=mid+1;
        }
        if(sums[l]>=t)return l;
        return 0;
    }
    int minSubArrayLen(int target, vector<int>& nums) {
    int ans=INT_MAX;
    int n=nums.size();
    if(n==0)return 0;
    int l,r;
    vector<int>sums(n+2,0);//开一个大一点得vector数组,因为这里使用前缀和数组用1开始做下标
    for(int i=1;i<=n;i++)sums[i]=sums[i-1]+nums[i-1];//前缀和
    for(int i=1;i<=n;i++)
    {
        int t=target+sums[i-1];//寻找sums[r]-sums[l-1]>=target,转化为寻找sums[r]>=sum[l-1]+target
        l=0,r=n;
        int x=binary_serach(t,l,r,sums);
        if(x)ans=min(ans,x-(i-1));
    }
    if(ans==INT_MAX)return 0;
    return ans;
    }
};
-  双指针&滑动窗口 设置两个指针i和j,j一直向右移动,i符合条件才移动 因为是寻找长度最小的子数组,当sum>=target时,记录长度,然后i要向右移动,当sum<target时j继续移动,寻找下一个sum>=target的条件 class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int n=nums.size(); int ans=INT_MAX; long long sum=0; for(int i=0,j=0;j<n;) { sum+=nums[j]; while(sum>=target) { ans=min(ans,j-i+1); sum=sum-nums[i]; i++; } j++; } if(ans==INT_MAX)return 0; return ans; } };网友的理解方式通俗易懂 
  



















