zoukankan      html  css  js  c++  java
  • LeetCode 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).


    题目标签:Array, Two Pointers, Binary Search

      题目给了一个数组,和一个 s, 让我们找到一个 最短的连续子数组,它的数组之和大于等于 s。

      题目说了两种方法:O(n) 和 O(n log n)

      方法1: O(n) 利用 Two Pointers

      设一个start 和一个 end,用sliding window, 一个窗口,start 到 end。

      当 这个窗口的sum 小于 s 的时候,说明数字还不够大,需要更多数字,就延伸右边的 end 来得到更多数字;

      当 这个窗口的sum 大于等于 s 的时候,说明 我们得到了一个 可能是答案的 window size,我们需要最小的。 然后把左边的start 向右延伸,继续寻找新的可能性。

      

    Java Solution:

    Runtime beats 24.17% 

    完成日期:09/04/2017

    关键词:Array,Two Pointers

    关键点:Sliding window 控制左右边界,来找到最小的符合要求的 window size

     1 class Solution 
     2 {
     3     public int minSubArrayLen(int s, int[] nums) 
     4     {
     5         /* Solution 1: O(n)*/
     6         if(nums.length == 0)
     7             return 0;
     8 
     9         int start = 0;
    10         int end = 0;
    11         int res = Integer.MAX_VALUE;
    12         int sum = nums[start];
    13         
    14         while(true)
    15         {
    16             if(sum < s)
    17             {
    18                 // shift end to right one place
    19                 if(end + 1 == nums.length)
    20                     break;
    21                 
    22                 sum += nums[++end];
    23             }
    24             else if(sum >= s)
    25             {
    26                 // get the smaller size
    27                 res = Math.min(res, end - start + 1);
    28                 
    29                 if(end == start)
    30                     break;
    31                 
    32                 // shift start to right one place
    33                 sum -= nums[start++];
    34             }
    35         }
    36         
    37         if(res == Integer.MAX_VALUE)
    38             res = 0;
    39         
    40         return res;
    41     }
    42 }

      方法2:O(n log n) 利用 二分法来找到最小符合要求的 window size

      要利用 binary search 的话,需要一个有序的数组,所以我们需要新设一个 原nums size + 1 的新 array sums, 把每一个从0 到 i (在nums中) 的sum 存入 新 array 的 index 1 到最后。

      所以新的array 里, 从index 1 到最后的 每一个值 都是 原nums 相对应的 0 到 i 的sum。

      原题例子:

      nums 2 3 1 2 4 3    原 array

      sums 0 2 5 6 8 12 15  新 array 第一个位置不用,后面每一个数字都是 nums 里相对应的sum值

      在有了这个有序数组之后, 可以遍历新 array index 1 开始的每一个数字, 找到每一个最小的右边边界 (sums[i] + s) ,然后记录一个最小的window size 就可以了。

    Java Solution:

    Runtime beats 12.29% 

    完成日期:09/04/2017

    关键词:Array,Binary Search

    关键点:新建一个 ascending sums array 对应 nums array;

        用二分法找到符合s要求的最小的window size

     1 class Solution 
     2 {
     3     public int minSubArrayLen(int s, int[] nums) 
     4     {
     5         int[] sums = new int[nums.length + 1];
     6         
     7         for (int i = 1; i < sums.length; i++) 
     8             sums[i] = sums[i - 1] + nums[i - 1];
     9         
    10         int minLen = Integer.MAX_VALUE;
    11         
    12         for (int i = 0; i < sums.length; i++) 
    13         {
    14             int end = binarySearch(i + 1, sums.length - 1, sums[i] + s, sums);
    15             
    16             if (end == sums.length) 
    17                 break;
    18             
    19             if (end - i < minLen) 
    20                 minLen = end - i;
    21         }
    22         return minLen == Integer.MAX_VALUE ? 0 : minLen;
    23     }
    24     
    25     public int binarySearch(int lo, int hi, int key, int[] sums) 
    26     {
    27         while (lo <= hi) 
    28         {
    29            int mid = (lo + hi) / 2;
    30            
    31            if (sums[mid] >= key)
    32                hi = mid - 1;
    33            else 
    34                lo = mid + 1;
    35            
    36         }
    37         return lo;
    38     }
    39 }

    参考资料:

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

      

    LeetCode 算法题目列表 - LeetCode Algorithms Questions List

  • 相关阅读:
    POJ1995 ZOJ2150 Raising Modulo Numbers【快速模幂】
    POJ3641 UVA11287 HDU1905 Pseudoprime numbers【素数判定+快速模幂】
    ACM题解系列之三:秋田拓哉:《挑战程序设计竞赛》(第2版)
    HDU3257 Hello World!【打印图案+位运算】
    ACM题解系列之二:刘汝佳:《算法竞赛入门经典训练指南》
    UVa10881 Piotr's Ants【模拟】
    POJ1852 UVa10714 Ants【水题】
    剑指Offer——平衡二叉树
    剑指Offer——二叉树的深度
    剑指Offer——数字在排序数组中出现的次数
  • 原文地址:https://www.cnblogs.com/jimmycheng/p/7477562.html
Copyright © 2011-2022 走看看