LeetCode OJ 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.

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

Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.


【题目分析】

给定一个由n个正数组成的数组一个目标值s,找到大于等于目标值的最短子数组的长度,如果不存在就返回0。


【思路】

1. 时间复杂度为O(n)

为了找到最小的子数组,并且子数组元素的和值要大于等于s,我们要找到子数组的起始点和终止节点。假设我们已经找到了一个满足条件的子数组,下一步该怎么办呢?

为了使得数组的长度最短,我们要把起始点向后移动,如果还满足条件就继续向后移动。如果条件不满足了,我们就把终止节点向后移动,然后重复上面的过程。举个例子如下:nums: [2,3,1,2,4,3],s=7。

(1)begin=0, end=0, sum=2,minlen=nums.length+1; 此时sum<7,end向后移动。

(2)sum=5,end继续向后移动。

(3)sum=6,end继续向后移动。

(4)sum=8,begin向后移动,minlen=4。

(5)sum=6,end向后移动。

(6)sum=9,begin向后移动,minlen=4。

(7)sum=7,begin继续向后移动,minlen=3。

(8)sum=6,end向后移动。

(9)sum=9,begin向后移动,minlen=3.

(10)sum=7,begin向后移动,minlen=2.

(11)结束,返回2.

2. 时间复杂度为nO(logn)

 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.

由于数组中所有元素是正数,因此向后累加的和值肯定是递增的。一个子数组的和可以表示为两个不同位置数组累加和的差值。所以我们构造一个数组累加和的数组,然后使用二分查找来解决这个问题。

例如 nums:[2,3,1,2,4,3],s=7。累加和数组sums:[0,2,5,6,8,12,15].

我们遍历sums数组,对于每一个元素sum[i],向后找到第一个比sums[i]+s大的元素,然后计算此时的minlen的长度。返回最小的即可。


【java代码1】O(N)

 1 public class Solution {
 2     public int minSubArrayLen(int s, int[] nums) {
 3         if(nums == null || nums.length == 0) return 0;
 4         
 5         int begin = 0, end = 0;
 6         int sum = nums[0], minlen = nums.length + 1;
 7         
 8         while(end < nums.length){
 9             if(sum < s){
10                 if(end < nums.length-1)
11                     sum += nums[++end];
12                 else break;
13             }
14             else{
15                 minlen = Math.min(minlen, end-begin+1);
16                 sum = sum - nums[begin++];
17             }
18         }
19         
20         return minlen <= nums.length ? minlen : 0;
21     }
22 }

 

【java代码1】NO(logN)

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

 

转载于:https://www.cnblogs.com/liujinhong/p/5639460.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值