問題描述:
Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.
Example:
Input:s = 7, nums = [2,3,1,2,4,3]
Output: 2 Explanation: the subarray[4,3]
has the minimal length under the problem constraint.
Follow up:
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^2)的方法。Solution給的解法,用sums[i]存儲i-1下標之前的和。然後每次判斷sums[i]-sums[j]是否大於s且i-j+1是當前最小值,是就換。但是可能用例更行的原因,最後一個用例已經無法通過了。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n=nums.size(), result=INT_MAX, sum=0;
vector<int> sums(n+1, 0);
for (int i=1; i<=n; i++){
sums[i] += sums[i-1]+nums[i-1];
for(int j=i-1; j>=0; j--){
if(sums[i]-sums[j] >= s){
result = min(result, i-j);
}
}
}
return result!=INT_MAX? result: 0;
}
};
二分查找法:還是用用sums[i]存儲i-1下標之前的和,用二分查找找大於等於sums[i]+s的下標。時間複雜度O(nlogn)。
學習到了Low_bound函數,詳情可查看lower_bound 與 upper_bound 函數。
static_cast是強制轉換
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n=nums.size(), result=INT_MAX;
vector<int> sums(n+1, 0);
for(int i=1; i<=n; i++){
sums[i] = sums[i-1] + nums[i-1];
}
for(int i=1; i<=n; i++){
int tmp = sums[i-1] + s;
auto bound = lower_bound(sums.begin()+i-1, sums.end(), tmp);
if (bound != sums.end()){
result = min(result, static_cast<int>(bound - (sums.begin()+i-1)));
}
}
return result!=INT_MAX? result: 0;
}
};
雙指針法,用一個sum保存所有的值的和,用left保存第一個值的位置,每次減去第一個值,看看結果是否大於s。這樣每次再判斷一下result的最小值。該方法應該大概率是屬於O(n)的。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n = nums.size(), result=INT_MAX, left=0, sum=0;
for (int i=0; i<n; i++){
sum += nums[i];
while(sum >= s){
result = min(result, i+1-left);
sum = sum - nums[left++];
}
}
return result!=INT_MAX? result: 0;
}
};