题目描述
基本思路
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
从下到上
暴力法
双指针
前缀和+二分查找