209. Minimum Size Subarray Sum

本文探讨了给定一个正整数数组及目标值s,如何找到满足其和≥s的最小子数组长度。提供了三种方法:暴力法(O(n²))、二分查找改进(O(nlogn))及滑动窗口法(O(n)),并附带详细代码实现。

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn’t one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.

方法一:
brute-force, O(n^2)。不解释

int minSubArrayLen(int s, vector<int>& nums) {
    int i, j, sum;
    int minlen = INT_MAX;
    for (i = 0; i < nums.size(); i++) {
        sum = 0;
        for (j = i; j < nums.size(); j++) {
            sum += nums[j];
            if (sum >= s) {
                minlen = min(minlen, j - i + 1);
                break;
            } 
        }
    }
    if (minlen == INT_MAX) {
        return 0;
    }
    else return minlen;
}

方法二:binary search
binary search必须在有序数组上进行,当对原始数据的连续性有要求时,不能在原有基础上sorting。但是累加求和确是一种构造非递减数列的有效方法,前提是数组里都是非负数。这里就是如此。我们可以在求和之后将所有的和存起来,然后将问题转化为寻找sum[i] + s 的lower bound的问题,这里就可以用binary search将原本O(n)的复杂度降到O(logn).
代码:

int minSubArrayLen(int s, vector<int>& nums) {
    int i, j;
    int minlen = INT_MAX;
    int len = nums.size();
    vector<int> sum(len + 1, 0);
    for (i = 1; i <= len; i++) {
        sum[i] = sum[i - 1] + nums[i - 1];
    }
    for (i = 1; i <= len; i++) {
        int to_find = sum[i - 1] + s;
        j = binary_search(sum, to_find, i, len);
        if (j == -1) break;
        else minlen = min(minlen, j - i + 1);
    }
    return minlen == INT_MAX ? 0 : minlen;
}
int binary_search(vector<int>& sum, int to_find, int st, int ed) {
    if (st > ed) return -1;
    if (st == ed) {
        return sum[st] >= to_find ? st : -1;
    }

    int mid = (st + ed) / 2;

    if (to_find == sum[mid]) {
        return mid;
    }
    else if (to_find < sum[mid]) {
        return binary_search(sum, to_find, st, mid);
    }
    else {
        return binary_search(sum, to_find, mid + 1, ed);
    }
}

这里也可以直接用STL 库函数,lower_bound。返回有序数组里第一个大于等于to_find的数。
upper_bound是返回第一个大于to_find 的数。

方法三:滑动窗法
上述两种都是在固定starting index后逐一确定。其实对每个starting index有相当大的重复操作。
这里可以用两个指针,two pointers. 维持左右边界。非常简便。

int minSubArrayLen(int s, vector<int>& nums) {
    int left = 0, right = 0;
    int minlen = INT_MAX;
    int len = nums.size();
    int sum = 0;
    for (right = 0; right < len; right++) {
        sum += nums[right];
        while (sum >= s) {
            minlen = min(minlen, right - left + 1);
            sum -= nums[left++];
        }
    }
    return minlen == INT_MAX ? 0 : minlen;
}
This problem can be solved using binary search. We can try to find the minimum possible maximum sum in a subarray by binary searching over the range of possible values. The upper bound of this range is the sum of all elements in the array, since each subarray must have at least one element. The lower bound of this range is the maximum element in the array, since each subarray must have at least one element and the maximum element must be in its own subarray. For each guess of the maximum sum, we can try to divide the array into subarrays such that no subarray has a sum greater than the guess. This can be done by iterating through the array and greedily assigning each element to the current subarray until the sum of the subarray is greater than the guess. Then, we start a new subarray with the current element. If we can divide the array into k subarrays with a maximum sum no greater than our guess, we can try a smaller guess. If we cannot divide the array into k subarrays with a maximum sum no greater than our guess, we need to try a larger guess. Here's some sample code in Python: ``` n, k = map(int, input().split()) arr = list(map(int, input().split())) low = max(arr) high = sum(arr) while low < high: mid = (low + high) // 2 count = 1 total = 0 for x in arr: if total + x > mid: count += 1 total = x else: total += x if count > k: low = mid + 1 else: high = mid print(low) ``` This code reads in the input and initializes the range of possible values for the maximum sum in a subarray. Then, it performs binary search to find the minimum possible maximum sum. For each guess of the maximum sum, it tries to divide the array into k subarrays such that no subarray has a sum greater than the guess. If it can do this, it tries a smaller guess. If not, it tries a larger guess. Finally, it prints out the minimum possible maximum sum.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值