Minimum Size Subarray Sum

本文探讨了给定数组中寻找最小长度子数组使其和大于等于特定值的问题,提供了两种算法实现,分别是滑动窗口法与预处理数组结合二分查找法,并详细解释了这两种方法的思路及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目209:Minimum Size Subarray Sum

题目描述:
Given an array of n positive integers and a positive integer s, find the minimal length of a 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.

More practice:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
题目分析:
求和等于s的长度最小的子数组,子数组要求是连续的,子序列可以是不连续的,分别给出O(n)复杂度和O(nlogn)复杂度的两种解法。

1. 滑动窗口解法

思路分析:
滑动窗口,第一次看到有这样的解法,很巧妙,用两个指针left和right,分别指向滑动窗口的开始和结尾,如果滑动窗口中的和小于给定值,则滑动窗口的右边界向右滑,子数组和增加,直到滑动窗口内的子数组和>=给定值,比较最小长度和当前长度,然后滑动窗口左边界向右滑动。
那什么时候滑动结束呢?当滑动窗口的右边界right到达最右边,且滑动窗口内的子数组的和小于s时结束,不仅仅是滑动窗口右边界到达最右边就结束,因为此时左边界可能还可以滑动。

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int res, fast, slow, len, sum;
        len = nums.size();
        if (len == 0)
            return 0;
        fast = 0;
        slow = 0;
        /* 
         * res最大值是len+1,而不是len,因为如果是len,不能判断
         * 是否是没找到,因为还可以是数组所以内容和==s的情况
         */
        res = len + 1;
        sum = nums[0];
        while (fast < len) {
            while (sum < s && fast < len)
                sum += nums[++ fast];
            if (sum >= s) {
                res = min(res, fast - slow + 1);
                sum -= nums[slow ++];
            }
        }
        return res == len + 1 ? 0 : res;
    }
};

2. 预处理数组解法

思路分析:
采用预处理数组的解法,建立sum[len + 1]数组,sum[i]表示nums[1…i - 1]子数组的和,也就是下标i之前数组的和,然后对应每一个sum[i],用二分查找法找到子数组的右边界,使该子数组的和大于sum[i] + s,然后更新最小长度。很巧妙的解法。

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int len = nums.size();
        if (len == 0)
            return 0;
        vector<int> sum(len + 1);
        int i, res;
        sum[0] = 0;
        res = len + 1;
        for (i = 1; i < len + 1; i ++)
            sum[i] = sum[i - 1] + nums[i - 1];
        for (i = 0;i < len + 1; i ++) {
            /* 参数是sum数组中的下标 */
            int right = BinarySearch(sum, i + 1, len, sum[i] + s);
            if (right == len + 1)
                break;
            if (res > right - i)
                res = right - i;
        }
        return res == len + 1 ? 0 : res;
    }
    int BinarySearch(vector<int> sum, int left, int right, int key) {
        while (left <= right) {
            int mid = (left + right) / 2;
            if (sum[mid] >= key)
                right = mid - 1;
            else
                left = mid + 1;
        }
        return left;
    }
};

参考:http://www.cnblogs.com/grandyang/p/4501934.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值