209. 长度最小的子数组. ①前缀和加二分②双指针

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 0。

示例:

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1.前缀和加二分 O(nlogn)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        vector <int> presum(n + 1, 0);

        presum[0] = 0;
        for (int i = 1; i <= n; i++){
            presum[i] = presum[i - 1] + nums[i - 1];
        }

        int l = 1, r = n;
        while (l <= r){
            int mid = (l + r) / 2;
            if (check(mid, presum, n, s)){
                r = mid - 1;
            }
            else{
                l = mid + 1;
            }
        }

        if (check(l - 1, presum, n, s)) return l - 1;
        if (check(l, presum, n, s)) return l;
        return 0;
    }

    bool check(int len, vector<int> presum, int n, int s){
        for (int i = 0; i < n - len + 1; i++){
            if(presum[i + len] - presum[i] >= s){
                return true;
            }
        }
        return false;
    }
};

2.双指针

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();

        int ans = INT_MAX;
        int l = 0, r = 0;
        int sum = 0;

        while (r < n){
            sum += nums[r];
            while (sum >= s){
                ans = min(ans, r - l + 1);
                sum -=nums[l];
                l++;
            }
            r++;
        }

        return ans == INT_MAX ? 0 : ans;
    }
};
posted @ 2020-06-28 22:15  _西瓜不甜  阅读(130)  评论(0编辑  收藏  举报