LeetCode/solutions/209. Minimum Size Subarray Sum.md
2019-09-07 12:38:29 +08:00

2.1 KiB
Raw Blame History

209. Minimum Size Subarray Sum

思路

给定一个全为正数的数组和一个数字让求连续子数组之和大于等于给定值的最小子数组长度要求用O(n)和O(nlogn)两种思路。

思路一

先看O(n)的解法我们维护一个整数sum和两个指针left和right表示子数组的范围初始均为0然后向右移动right并累加sum直到sum >= s 然后尝试(需保证sum >= s右移左指针left此时right - left + 1即一个候选长度。

思路二

再看O(nlogn)的思路,由于给定数组全是正数,所以从左往右累加结果是递增的,即我们可以考虑二分法。 思路是,建立一个比原数组长一位的 sums 数组,其中 sums[0]=0; sums[i] = sum(nums[0,...,i-1]) 对于每个i使得sums[i] >= s, 我们用二分法找到一个j使得满足sums[j] > sums[i] - s (j < i),即可得到候选长度i-j+1

注意不用自己实现二分STL里lower_bound和upper_bound已经实现好了注意学习其用法。

C++

思路一

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        int left = 0, right = 0, sum = 0, res = INT_MAX;
        
        for(; right < n; right++){ // 不断向右移动right
            sum += nums[right];
            while(sum >= s){ // 尝试右移左指针left
                res = min(res, right - left + 1);
                sum -= nums[left++];
            }
        }
        return res == INT_MAX ? 0 : res;
    }
};

思路二

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size(), res = INT_MAX;
        vector<int> sums(n + 1, 0);
        for (int i = 1; i <= n; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        for (int i = n; i >= 0 && sums[i] >= s; i--) {
            int j = upper_bound(sums.begin(), sums.end(), sums[i] - s) - sums.begin();
            res = min(res, i - j + 1);
        }
        return res == INT_MAX ? 0 : res;
    }
};