leetcode 209. 长度最小的子数组(详解)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

思路:

  • 暴力算法:使用两个for循环,不断的寻找符合条件的子数组
    leetcode 209. 长度最小的子数组(详解)_第1张图片

  • 滑动窗口:不断地调节子数组的起始位置和终止位置,从而得出我们想要的结果

  • 实现滑动窗口步骤:

    1. 窗口内的元素:保持窗口内数值总和大于或等于target的长度最小的连续子数组
    1. 移动窗口的起始位置:如果当前窗口的值大于s,则窗口向前移动(窗口缩小)
    1. 移动窗口的结束位置:窗口的结束位置就是for循环遍历数组的指针

leetcode 209. 长度最小的子数组(详解)_第2张图片

代码如下:
1.暴力解法

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result=INT32_MAX;//最终结果
        int sum=0;//子数组的元素之和
        int countlen=0;  //子数组的长度
        for(int i=0;i<nums.size();i++)  //设置子数组起点为i
        {
            sum=0;
            for(int j=i;j<nums.size();j++) //设置子数组最终位置为j
            {
                sum+=nums[j];
                if(sum>=target)  //一旦发现子数组元素之和超过target就更新result
                {
                    countlen=j-i+1; //获取子数组的长度
                    result=countlen<result?countlen:result;
                    break;
                }
            }
        }
        //   如果result没有被赋值,则返回0,说明没有符合条件的子数组
        if(result==INT32_MAX)
            return 0;
        return result;

    }
};
  • 时间复杂度O(N^2)
  • 空间复杂度O(1)

2. 滑动窗口

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result=INT32_MAX;
        int i=0;   //滑动窗口的起始位置
        int sum=0; //滑动窗口的数值之和
        int countlen=0;   //滑动窗口的长度
        for(int j=0;j<nums.size();j++)
        {
            sum+=nums[j];
            //注意这里使用while每次更新i(起始位置)并不断比较子数组是否符合条件
            while(sum>=target)
            {
                countlen=j-i+1; //获取子数组的长度
                result=result<countlen?result:countlen;
                //这里体现出滑动窗口的精髓之处,不断变更i(子数组的起始位置)
                sum-=nums[i++];
            }
        }
        //   如果result没有被赋值,则返回0,说明没有符合条件的子数组
        return result==INT32_MAX?0:result;
    }
};
  • 时间复杂度O(N)
  • 空间复杂度O(1)

总结:滑动窗口的精妙之处在于根据当前子数组和的大小,不断调节子数组的起始位置,从而将时间复杂度O(N^2)降为O(N)

你可能感兴趣的:(leetcode,leetcode,算法,职场和发展,C++,数据结构)