「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 ≤ t a r g e t ≥ 1 0 9 1 \le target \ge 10^9 1≤target≥109
  • 1 ≤ n u m s . l e n g t h ≥ 1 0 5 1 \le nums.length \ge 10^5 1≤nums.length≥105
  • 1 ≤ n u m s [ i ] ≥ 1 0 5 1 \le nums[i] \ge 10^5 1≤nums[i]≥105

✏️题目解析 & 思路

题目要求我们在数组中寻找和为target的最小子数组,我们可以先去想出暴力解法,然后再推算出滑动窗口的解法。

暴力法

我们需要找到最短的连续数组,那么最简单的方式就是用两个for循环去遍历数组累加数值,只要数值 ≥ t a r g e t \ge target ≥target 就更新最小长度的状态。

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int ret = INT_MAX;
        for(int left = 0; left < n; ++left)
        {
            int sum = 0;
            for(int right = left; right < n; ++right)	
            {
                sum += nums[right];						//累加数据
                if(sum >= target)
                {
                    ret = min(ret, right - left + 1);	//更新状态
                    break;								//已经找到了最小的长度,所以退出该层循环
                }
            }
        }
        
        return ret == INT_MAX ? 0 : ret;
    }
};

时间复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( 1 ) O(1) O(1)

滑动窗口

滑动窗口的题目大抵都有一个固定的划分过程:

  1. ++right
  2. 进窗口
  3. 判断
    • 更新结果状态(根据题目不同,也可能在判断后更新状态)
    • 出窗口(++left)

我们从暴力法中不难发现,其实当我们更新最小子数组长度时, l e f t + 1 → r i g h t left+1\to right left+1→right 的这段区间是重复遍历的,于是我们便可以使用滑动窗口来进行优化。当我们的 s u m ≥ t a r g e t sum \ge target sum≥target 时,同时更新 l e f t left left 的位置 与 最小子数组的长度,所谓的滑动窗口也是一种特殊的双指针类型,只不过两个指针的指向都是相同的方向。

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int sum = 0, ret = INT_MAX;
        for(int left = 0, right = 0; right < n; ++right)
        {
            sum += nums[right];		//进窗口
            while(sum >= target)	//判断
            {
                ret = min(ret, right-left+1);	//更新状态
                sum -= nums[left++];			//出窗口
            }
        }

        return ret == INT_MAX ? 0 : ret;	//返回结果
    }
};

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)

📓总结

📜博客主页:主页
📫我的专栏:C++
📱我的github:github

相关推荐
我命由我1234531 分钟前
Photoshop - Photoshop 工具栏(57)模糊工具
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
ldccorpora1 小时前
Multiple-Translation Arabic (MTA) Part 2数据集介绍,官网编号LDC2005T05
人工智能·深度学习·自然语言处理·动态规划·语音识别
Jasmine_llq1 小时前
《CF280C Game on Tree》
数据结构·算法·邻接表·深度优先搜索(dfs)·树的遍历 + 线性累加统计
小棠师姐2 小时前
支持向量机(SVM)入门:超平面与核函数的通俗解释
算法·python机器学习·支持向量机svm·超平面可视化·核函数应用
im_AMBER2 小时前
Leetcode 102 反转链表
数据结构·c++·学习·算法·leetcode·链表
今儿敲了吗2 小时前
01|多项式输出
c++·笔记·算法
Xの哲學3 小时前
深入剖析Linux文件系统数据结构实现机制
linux·运维·网络·数据结构·算法
AlenTech3 小时前
200. 岛屿数量 - 力扣(LeetCode)
算法·leetcode·职场和发展
C雨后彩虹3 小时前
竖直四子棋
java·数据结构·算法·华为·面试
不如自挂东南吱4 小时前
空间相关性 和 怎么捕捉空间相关性
人工智能·深度学习·算法·机器学习·时序数据库