- 问题描述: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. <p>For example, given the array
[2,3,1,2,4,3]
ands = 7
,the subarray[4,3]
has the minimal length under the problem constraint.</p> <p>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).</p>
- 问题分析:刚开始看到这个题时,并没有考虑到字数组连续的问题,发现只能用递归的解法,复杂度很高,后来搜了下,发现其实是自己理解的问题,这个题必须考虑到连续的问题。
- Solution 1: 这样O(n)的解法就很明显了,滑动窗口,两个指针即可解决。对数组中的每个数(左指针),计算从它开始往右的和,直到不小于s为止(右指针),然后更新这个长度,随后左指针右移,直至从当前左指针到右指针的和小于s为止。此外,这个题可能发生整个数组和小于s的情况,所以只需要在minLen的初始值设置为大于nums.legth,最后在发挥至的时候判断下即可解决。
- For example:对当前例子中的数组,left = 0, right = 3.即从2到下一个2为止这个字数组和(8)是超出s(8),然后left右移, 发现left=1时,字数组和变味了8-2=6,所以 从当前的左指针开始,右指针开始移动.这样不断更新这个值即可。代码如下:
public class Solution { public int minSubArrayLen(int s, int[] nums) { if (nums == null || s <= 0) return 0; //滑动窗口 int left = 0, right = 0, len = nums.length + 1, temp = 0; while(right < nums.length){ while(right < nums.length && temp < s){ temp += nums[right++]; } while(temp >= s){ len = Math.min(len, right - left); temp -= nums[left++]; } } return len == nums.length + 1? 0 : len; } }
- Solution 2:more practice要求给出O(nlogn)的解法,实在是很不明白,这个题O(n)的解法已经非常清晰明了,为何还要给出复杂度高的解法,可既然是题目要求,那就尝试接下去,看到log(n),首先就想到了二分查找,可是如何利用二分查找,因为二分查找要求查找的数组有序,那就让数组变得有序即可。让数组变得有序秩序再申请一个数组sums, 其中sums[i] 代表nums[0...i-1]的和。这样对么个sums[i],计算右边界即可。右边界是sums[high] >sums[low] + s的值。其实从这既可以看出,这有解法一并没有本质的区别.另外,这个解法还要注意,一旦sums[low] + s超出了sums[sums.length-1],即说明后边不肯能有满足条件的解了,停止搜索.代码如下:
public class Solution { public int minSubArrayLen(int s, int[] nums) { if (nums == null || s <= 0) return 0; int[] sums = new int[nums.length + 1]; for(int i = 1; i <= nums.length; i++){ sums[i] = sums[i-1] + nums[i-1]; } if(sums[sums.length - 1] < s) return 0; int len = sums.length,low, high, target, mid; for(int i = 0; i < sums.length; i++){ low = i+ 1;high = sums.length-1; target = sums[i] + s; while(low <= high){ mid = low + ((high - low) >> 1); if(sums[mid] >= target) high = mid - 1; else if (sums[mid] < target) low = mid + 1; } if(low >= sums.length) break; if(low - i < len) len = low - i; } return len; } }
此外,本文的解法在http://www.cnblogs.com/grandyang/p/4501934.html的基础上而来,特此声明。