长度最小的满足和的子数组

原题在这里

概述题意:

  给定数组中,求满足和>=target的子数组的最小数组长度。

1.暴力是不可能暴力的,再怎么说都是维护dp[i]=nums[i,r]

class Solution
{
public:
    int minSubArrayLen(int target, vector<int> &nums)
    {
        int l = nums.size(), r = 0, ans = l * 2;
        vector<int> dp(l, 0);
        // dp[i]=nums[i,r-1]
        for (int i = 0; i < l; ++i)
        {
            if (i != 0)
                dp[i] = dp[i - 1] - nums[i - 1];
            while (dp[i] < target)
            {
                if (r == l)
                    break;
                dp[i] += nums[r++];
            }
            while (dp[i] - nums[r - 1] >= target)
                dp[i] -= nums[--r];
            if (dp[i] >= target)
                ans = min(ans, r - i);
        }
        return ans == l * 2 ? 0 : ans;
    }
};
动态规划维护target

2.前缀和+二分搜索

逻辑很简单,但是巧妙在于二分搜索的运用:

code:

class Solution
{
public:
    int minSubArrayLen(int target, vector<int> &nums)
    {
        int l = nums.size(), r = 0, ans = l * 2;
        vector<int> sum(l + 1, 0);
        for (int i = 1; i <= l; ++i)
            sum[i] = sum[i - 1] + nums[i - 1];
        for (int i = 1; i <= l; ++i)
        {
            int x = target + sum[i - 1]; //找第一个大于等于x的值
            auto id = lower_bound(sum.begin(), sum.end(), x);
            if (id != sum.end())
                ans = min(ans, (int)(id - sum.begin() - i + 1));
        }
        return ans == l * 2 ? 0 : ans;
    }
};
寻找target+sum[i-1]

3.滑动窗口,同方法一,时间复杂度也是线性的,优于空间复杂度:

code:

class Solution
{
public:
    int minSubArrayLen(int target, vector<int> &nums)
    {
        int n = nums.size(), l = 0, r = 0, ans = n * 2;
        int sum = 0;
        while (r < n)
        {
            sum += nums[r];
            while (sum >= target)
            {
                ans = min(ans, r - l + 1);
                sum -= nums[l++];
            }
            ++r;
        }
        return ans == n * 2 ? 0 : ans;
    }
};

【Over】

posted @ 2022-03-24 15:41  Renhr  阅读(25)  评论(0)    收藏  举报