xinyu04

导航

LeetCode 209 Minimum Size Subarray Sum 滑动窗口 & 二分答案

Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [numsl, numsl+1, ..., numsr-1, numsr] of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.

Solution

求最小的序列长度满足区间和 \(\ge \text{target}\).

1. \(O(n)\)

和上一道题类似,利用滑动窗口的思想。我们用 \(cur\) 记录当前的 \(sum\),如果满足 \(cur\ge target\), 就不断缩短左端点 \(l\), 然后更新答案。

点击查看代码
class Solution {
private:
    int ans = INT_MAX;
    
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int l=0,r=0;
        int cur=0;
        while(r<n){
            cur+=nums[r];
            while(cur>=target){
                ans=min(ans,r-l+1);
                cur-=nums[l];l++;
            }
            r++;
        }
        
        return ((ans==INT_MAX)?0:ans);
    }
};

2. \(O(n\log n)\)

考虑前缀和 \(sum\):

\[sum[i]=sum[i-1]+nums[i] \]

我们从后往前遍历,然后利用 \(upper\_bound\) 来求出 \(j\) 满足:

\[sum[j]>sum[i]-s \]

改写一下得到:

\[sum[i]-sum[j]<s \]

除此以外,我们还有:

\[sum[i]-sum[j-1]\ge s \]

因此 \(nums[i]\sim nums[j]\) 是区间答案。

点击查看代码
class Solution {
private:
    int ans = INT_MAX;
    
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        vector<int> sum(n+1,0);
        for(int i=0;i<n;i++){
            sum[i+1] = sum[i]+nums[i];
        }
        // find a j : sum[j] > sum[i]-s
        // ---> sum[i]-sum[j]<s && sum[i]-sum[j-1]>=s
        // therefore: minimum length: i-j+1
        for(int i=n;i>=1;i--){
            if(sum[i]>=target){
                int j = upper_bound(sum.begin(),sum.end(),sum[i]-target)-sum.begin();
                ans=min(ans,i-j+1);
            }
        }
        return ((ans==INT_MAX)?0:ans);
    }
};

posted on 2022-08-01 23:56  Blackzxy  阅读(19)  评论(0编辑  收藏  举报