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.
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).
滑动窗口的思想,O(n)。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int sum = 0;
int length = nums.size() + 1;
for(int start = 0, cur = 0; cur < nums.size(); ++cur) {
sum += nums[cur];
if (sum >= s) {
while (sum - nums[start] >= s) {
sum -= nums[start++];
}
length = min(length, cur - start + 1);
}
}
if (length > nums.size()) {
length = 0;
}
return length;
}
};
O(nlogn)的话用分治法,这个比较复杂,很容易出错,各种边界条件。关键是求跨两边的那个最短子数组,先往左找到符合条件的,然后往右滑动。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
return minSubUtil(s, nums, 0, nums.size() -1);
}
int minSubUtil(int s, const vector<int>& nums, int start, int end) {
if (start > end) {
return 0;
}
else if (start == end) {
return (nums[start] >= s ? 1: 0);
}
int mid = (start + end) / 2;
int len1 = minSubUtil(s, nums, start, mid);
int len2 = minSubUtil(s, nums, mid + 1, end);
int minLength = min(len1, len2);
if (len1 == 0 || len2 == 0) {
minLength = max(len1, len2);
}
int len3 = 2;
int sum = nums[mid] + nums[mid+1];
int left = mid;
while (sum < s && left > start) {
sum += nums[--left];
++len3;
}
int right = mid + 1;
while (sum < s && right < end) {
sum += nums[++right];
++len3;
}
if (sum >= s) {
if (minLength == 0) {
minLength = len3;
}
else {
minLength = min(minLength, len3);
}
while (left < mid) {
sum -= nums[left++];
--len3;
while (sum < s && right < end) {
sum += nums[++right];
++len3;
}
if (sum < s) {
break;
}
else {
minLength = min(minLength, len3);
}
}
}
return minLength;
}
};