題目描述
基本思路
1.暴力枚舉法 o(n^2);
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int n = nums.size();
if (n == 0) {
return 0;
}
int ans = INT_MAX;
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += nums[j];
if (sum >= s) {
ans = min(ans, j - i + 1);
break;
}
}
}
return ans == INT_MAX ? 0 : ans;
}
};
2.雙指針法 時間o(n)
class Solution {
public:
int left,right;
int minSubArrayLen(int s, vector<int>& nums) {
int sum=0,ans=INT_MAX;
int len=nums.size();
if(len==0) return 0;
while(right<len)
{
sum+=nums[right];
while(sum>=s)
{
ans=min(ans,right-left+1);
sum-=nums[left];
left++;
}
right++;
}
return ans==INT_MAX?0:ans;
}
};
前綴和+二分搜索
注意題目保證了所有的數據都是正數
所以可以知道前綴和就一定爲遞增序列
則可以再次使用二分查找把查找的時間複雜度降到o(logn)
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int len=nums.size();
int ans=INT_MAX;
vector<int> sum(len+1,0);
for(int i=1;i<=len;i++)
{
sum[i]=sum[i-1]+nums[i-1];//前綴和 sum[i]代表前i個數之合
}
for(int i=1;i<=len;i++)
{
int target=s+sum[i-1];
auto bound=lower_bound(sum.begin(),sum.end(),target);//c++自帶的二分查找函數
if(bound!=sum.end())
{
ans=min(ans,static_cast<int>((bound - sum.begin()) - (i - 1)));
}
}
return ans==INT_MAX?0:ans;
}
};
提交oj
從下到上
暴力法
雙指針
前綴和+二分查找