题目:
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.
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
解答:1.O(n) two points
用begins指针记录子串开头的位置,每次遍历一个字符,判断sum是否大于s,若是,则将该sum记录minlen中(sum<minlen);然后将begins+1,并将nums[begin]元素减去;若sum小于s,则 i+1, 且将其值加入sum中。以下为我的代码:
class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { int begins = 0; int len = nums.size(); if(len == 0) return 0; if(len==1){ if(nums[0]==s) return 1; else return 0; } int minlen = len+1; int sum = nums[0]; int i = 0; while(i < len){ if(sum >= s){ int l = i - begins+1; if(l < minlen) minlen = l; sum = sum-nums[begins]; ++begins; }else{ if(i+1>=len) break; sum = sum+nums[++i]; } } if(minlen == len+1) return 0; else return minlen; } };
O(n)
class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { int n = nums.size(), start = 0, sum = 0, minlen = INT_MAX; for (int i = 0; i < n; i++) { sum += nums[i]; while (sum >= s) { minlen = min(minlen, i - start + 1); sum -= nums[start++]; } } return minlen == INT_MAX ? 0 : minlen; } };
对于要求该复杂度,就要想到二分查找的方法。但是二分查找是对递增序列的,而原序列无法进行更改顺序,因此怎么找递增序列呢? 那就找从开头到每个元素的和的序列。如: nums=[2,3,1,2,4,3]序列,则sums=[0,2,5,6,8,12,15].然后对于每个元素sums[i],找sums数组中大于sums[i]+s的值,用二分查找。找到后的位置j-i就是要求的长度。
这里调用别人的优秀的代码:
class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { int len = nums.size(), sums[len + 1] = {0}, res = len + 1; for (int i = 1; i < len + 1; ++i) sums[i] = sums[i - 1] + nums[i - 1]; for (int i = 0; i < len + 1; ++i) { int right = searchRight(i + 1, len, sums[i] + s, sums); if (right == len + 1) break; if (res > right - i) res = right - i; } return res == len + 1 ? 0 : res; } int searchRight(int left, int right, int key, int sums[]) { while (left <= right) { int mid = (left + right) / 2; if (sums[mid] >= key) right = mid - 1; else left = mid + 1; } return left; } };