209. Minimum Size Subarray Sum

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

Approach#1 Brute Force

Brute force方法就是两个循环,start和end指针之间的数加起来。复杂度O(n2),一次AC。没毛病,老铁。

    /**
     * O(n^2)
     */
    public int minSubArrayLen0(int s, int[] nums) {
        int minLen = Integer.MAX_VALUE;
        for (int i = 0; i < nums.length; i++) {
            int sum = 0;
            for (int j = i; j < nums.length; j++) {
                sum += nums[j];
                if (sum >= s) {
                    //Math.min..
                    minLen = j - i + 1 < minLen ? j - i + 1 : minLen;
                    break;
                }
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }

Approach #2 Sliding Window

我想了类似的题目比如subarray sum equals k,523. Continuous Subarray Sum等等,都是用一个map储存过往的值,然后要么减去k,要么mod k;所以这题我也想map,结果发现这个是要求>=一个值而不是一个精确值,有可能map不到啊。跟567. Permutation in String类似用Sliding window,两个指针。

然后我就看答案了。O(n)做法像下面这样,竟然不需要用map。
两层while,乍看上去像是O(n2),其实是O(n)。
而且,貌似用for不太方便,只能用while。
而且,subarray sum equals k那题用这个方法似乎不太可行。

    /**
     * O(n)
     */
    public int minSubArrayLen(int s, int[] nums) {
        if (nums == null || nums.length == 0)
            return 0;
        
        int minLen = Integer.MAX_VALUE;
        int sum = 0;
        int j = 0;
        int i = 0;
        while (j < nums.length) {
            sum += nums[j++];
            while (sum >= s) {
                minLen = Math.min(minLen, j - 1 - i + 1);
                sum -= nums[i++];
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen ;
    }

approach3 binary search

另外贴一个O(nlogn)的解法,我没动手做了:

    private int solveNLogN(int s, int[] nums) {
        int[] sums = new int[nums.length + 1];
        for (int i = 1; i < sums.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;
    }
    
    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;
    }

As to NLogN solution, logN immediately reminds you of binary search. In this case, you cannot sort as the current order actually matters. How does one get an ordered array then? Since all elements are positive, the cumulative sum must be strictly increasing. Then, a subarray sum can expressed as the difference between two cumulative sum. Hence, given a start index for the cumulative sum array, the other end index can be searched using binary search.

--

明天做76题或者Maximum Size Subarray Sum Equals k(我发现AC后推荐的题目很准确。。)

你可能感兴趣的:(209. Minimum Size Subarray Sum)