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.

click to show more practice.

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).

这个问题跟前面的最小窗口子串问题是类似。这里会介绍时间复杂度分别为 O ( n ) 和 O (n log n )的2种解法。

有2个指针,start, end 表示子串的开始和结束。

1. 从start index = 0 开始,先找到和满足要求的子串。

2. start++看看有没有更小的子串。

最小对求得的更小子串求min,得到最终的最小子串了。

这个算法的时间复杂度为 O ( n )。

运行时间:


代码:

    public int minSubArrayLen(int s, int[] nums) {
        int start = 0, end = 0, n = nums.length, curSum = 0, minLen = Integer.MAX_VALUE;
        while (end < n) {
            //find the valid window
            while (end < n && curSum < s) {
                curSum += nums[end++];
            }
            if (curSum < s) {
                break;
            }
            //try to find a smaller window
            while (start < end && curSum >= s) {
                curSum -= nums[start++];
            }
            if (end - start + 1 < minLen) {
                minLen = end - start + 1;
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }
O (n log n)的解法参考于:

https://discuss.leetcode.com/topic/13749/two-ac-solutions-in-java-with-time-complexity-of-n-and-nlogn-with-explanation

以:nums : [ 2 3 1 2 4 3], 求 s = 7为例。

我新创建一个累计和的数组 sums 为[ 0 2 5 6 8 12 15]。sums[ i ] 表示nums 中 index < i 的所有值的和。

对于nums, index = i  的时候,我想要找到跟 i 间隔值为s的下标。即在新数组中 >= sums[ i ] + s 值的下标。因为新数组是有序的,所以可以通过二分查找进行搜索。每次搜索的时间复杂度度为logN, 所有总的时间复杂度为O ( N log N )。

代码:

    private int binarySearch(int lo, int hi, int key, int[] sums) {
        while (lo <= hi) {
            int mid = (lo + hi) / 2;
            if (sums[mid] >= key) {
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
        }
        return lo;
    }

    public int solveNlogN(int s, int[] nums) {
        int[] sums = new int[nums.length + 1];
        for (int i = 1; i <= nums.length; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        int minLen = Integer.MAX_VALUE;
        for (int i = 0; i < sums.length; i++) {
            int end = binarySearch(i + 1, sums.length - 1, sums[i] + s, sums);
            if (end == sums.length) {
                break;
            }
            if (end - i < minLen) {
                minLen = end - i;
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值