题目:
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.
要求一个是O(n) 一个是O(lgn) 。
思路1:left、right两个指针,sum小于s的时候,right++,大于s的时候,left++,维护好sum的值即可,同时要判断数组的总和是否满足,时间复杂度为O(n)。
代码:
public class Solution { public int minSubArrayLen(int s, int[] nums) { int left = 0 ; int right = 0; int min = Integer.MAX_VALUE; int sum = 0; while(left <= right && right < nums.length){ sum += nums[right]; while(sum >= s && left <= right){ if(right - left + 1 < min) min = right - left + 1; sum -= nums[left]; left++; } right++; } if(min == Integer.MAX_VALUE) return 0; return min; } }
思路2:因为要O(lgn) 因此要用到二分法,需要一个单调的数列,因此,初始化一个辅助数列,存储前i位的和,思路1中right为线性扫描,十分耗时,可以用二分法来求得right值,即每一个left 满足要求的right。
代码:
public class Solution { public int minSubArrayLen(int s, int[] nums) { int len = nums.length; int min = Integer.MAX_VALUE; int[] snum = new int[len + 1]; for(int i = 1 ; i < len+1; i++) snum[i] = snum[i-1] + nums[i-1]; for(int i = 0 ; i < len; i++){ //每一个i为思路1中的left int left = i + 1; int right = len - 1; while(left <= right){ //二分法求思路1中的right int mid = (left + right) / 2; if(snum[mid] - snum[i] >= s) right = mid - 1; else left = mid + 1; } if(snum[left] - snum[i] >= s && left - i < min){ min = left - i; } } if(min == Integer.MAX_VALUE) return 0; return min; } }