一道题解释前缀和+二分查找【此后无良辰】

题目描述

在这里插入图片描述

基本思路

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

从下到上
暴力法
双指针
前缀和+二分查找
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章