leetcode 209.长度最小的子数组

1 题目描述

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

示例:

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2

解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。

2 解法

在做862时无意中做出了这个题。它和862的区别是,数组中的数都是正数。
在O(N)时间内计算nums的累积和数组sums,sums[i]=nums[0]+nums[1]+…+nums[i]。
假设当前窗口为k,在O(n)时间内可以计算出所有窗口大小为k的子数组的和,如果最大的比s小,要增大窗口,如果最大的比s大(或相等)就缩小窗口。这样最多lg(n)次循环就可以了。

3 java源码

class Solution {
    // A的累计和数组,sums[i] = sums(A[0]+A[1]+...+A[i])
    int[] sums;
    int K;
    int[] A;
    int minWindownSize;

    /**
     * 窗口大小固定时,计算每个窗口内所有值的和,返回最大的和
     * 时间复杂度为O(n)
     *
     * @param x 窗口大小
     * @return 最大的窗口内值的和
     */
    private int maxSumOverFixedSizeWindow(int x) {
        int max = sums[x-1];
        for (int i = 1; i < sums.length-x+1; i++) {
            int sum = sums[i+x-1]-sums[i-1];
            if (sum > max) max = sum;
        }
        return max;
    }

    /**
     * 可能的窗口范围在[min, max]之间,确定一个中间的数,然后递归查找
     * @param min
     * @param max
     * @return
     */
    private void find(int min, int max) {
        if (min > max) return;

        int x = (max-min)/2+min; // 窗口大小

        if (minWindownSize > 0 && minWindownSize <= x) return;

        int maxSum = maxSumOverFixedSizeWindow(x); // 窗口大小为x时,窗口内值的和最大为maxSum

        if (maxSum < K) { // 扩大窗口,没有找到,扩大窗口,看看能不能找到,可能会一直扩大到窗口为n,
            find(x+1, max);
            find(min, x-1);
        } else { // 缩小窗口 maxSum >= K,找到了,继续寻找有没有更好的,要一直缩小到窗口为1
            minWindownSize = x;
            find(min, x-1);
        }
    }

    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        if (n == 0) return 0;
        sums = new int[n];

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

        this.K = s;
        this.A = nums;
        this.minWindownSize = 0;

        for (int size = 1; size <= n; size*=2) {
            int maxSum = maxSumOverFixedSizeWindow(size);
            if (maxSum >= K) {
                minWindownSize = size;
            }
        }

        if (minWindownSize != 0) {
            find(1, minWindownSize);
        } else {
            find(1, n);
        }

        return this.minWindownSize;
    }
}

《leetcode 209.长度最小的子数组》

    原文作者:算法
    原文地址: https://www.twblogs.net/a/5bd3a8f32b717778ac20a8b8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞