当前位置: 首页 > news >正文

长度最小的子数组

滑动窗解法

算法题关键词:

满足xxx条件(计算结果,出现次数,同时包含)

最长/最短

字串/子数组/子序列

核心思想:

滑动窗使用思路(寻找最长)

——核心:左右双指针(R,L)在起始点,R向右逐位滑动循环

——每次滑动过程中

如果:窗内元素满足条件,R向右扩大窗口,并更新最优结果

如果:窗内元素不满足条件,L向右缩小窗口

——R到达结尾

滑动窗使用思路(寻找最短)

——核心:左右双指针(R,L)在起始点,R向右逐位滑动循环

——每次滑动过程中

如果:窗内元素满足条件,L向右缩小窗口,并更新最优结果

如果:窗内元素不满足条件,R向右扩大窗口

——R到达结尾

模板

最长模板:

初始化left,right,result,bestResult

while(右指针没有到达结尾)

{

        窗口扩大,加入right对应的元素,更新当前result

        while(result不满足要求)

        {

                窗口缩小,移除left对应元素,left右移

        }

        更新最优结果bestResult

        right++

}

最短模板:

初始化left,right,result,bestResult

while(右指针没有到达结尾)

{

        窗口扩大,加入right对应的元素,更新当前result

        while(result满足要求)

        {

                更新最优结果bestResult

                窗口缩小,移除left对应元素,left右移

        }       

        right++

}

返回bestResult

暴力解法

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;
    }
};

滑动窗口

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) 
        {
            return 0;
        }
        int ans = INT_MAX;
        int start = 0, end = 0;
        int sum = 0;
        while (end < n) 
        {
            sum += nums[end];
            while (sum >= s) 
             {
                ans = min(ans, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return ans == INT_MAX ? 0 : ans;
    }
};

滑动窗口是一种常用的算法技巧,适用于多种类型的题目,以下是一些常见的适用题型:
 

1. 子数组/子串问题

- 无重复字符的最长子串:例如给定一个字符串,要求找出其中不含有重复字符的最长子串的长度。像在字符串“abcabcbb”中,无重复字符的最长子串是“abc”,长度为3。这类问题可以通过滑动窗口不断扩大和缩小,同时利用哈希表等数据结构记录窗口内字符的出现情况,来高效地找到结果。
- 有k个不同字符的子串:给定一个字符串和一个整数k,找出字符串中包含k个不同字符的最长子串 。通过滑动窗口的移动,动态维护窗口内不同字符的数量和子串长度,从而找到满足条件的子串。
- 最小覆盖子串:给定两个字符串s和t,在s中找到包含t中所有字符的最小子串。利用滑动窗口不断调整子串的起始和结束位置,直到找到满足条件的最小子串。

2. 求子数组的最大/最小和、长度问题

- 和至少为K的最短子数组:给定一个整数数组和一个整数K,找出该数组中和至少为K的最短连续子数组的长度。通过滑动窗口的方法,不断调整窗口的起始和结束位置,计算窗口内子数组的和,从而找到满足条件的最短子数组长度。
- 长度为K的最大子数组和:在给定的数组中,找到长度为固定值K的连续子数组,使其元素和最大。通过滑动窗口在数组上滑动,每次计算窗口内的子数组和并进行比较,找到最大和的子数组。

3. 判断是否存在满足条件的区间

- 判断数组中是否存在和为目标值的连续子数组:给定一个整数数组和一个目标值,判断是否存在连续的子数组,其和等于目标值。可以通过滑动窗口在数组上移动,计算窗口内子数组的和,判断是否等于目标值。
- 判断字符串中是否存在异位词:给定两个字符串s和p,找出s中所有p的异位词的起始索引。通过滑动窗口在字符串s上滑动,利用数组或哈希表记录窗口内字符的出现次数,与字符串p的字符出现次数进行比较,判断是否为异位词。

4. 滑动窗口在其他场景的应用

- 在数据流中找特定模式:比如在不断到来的整数数据流中,找到满足特定条件(如连续若干个数的和在某个范围内)的子序列。
- 处理环形数组问题:对于环形数组(即数组的首尾相连),可以通过将数组长度翻倍等技巧,利用滑动窗口来处理一些与连续子数组相关的问题。

以下是一些力扣上典型的滑动窗口题目:


 1. 固定大小滑动窗口

- 题目1456. 定长子串中元音的最大数目
- 题目描述:给你字符串  s  和整数  k  ,请你返回  s  中长度为  k  的子串包含元音的最大数目。元音字母是  'a' 、 'e' 、 'i' 、 'o' 、 'u'  。
- 解题思路:维护一个长度为  k  的滑动窗口,统计窗口内元音的个数。每次窗口滑动时,移除左边离开窗口的字符(判断是否为元音,若是则从计数中减去),加入右边新进入窗口的字符(判断是否为元音,若是则增加计数) ,记录过程中的最大元音个数。
- 题目1343. 大小为 K 且平均值大于等于阈值的子数组数目
- 题目描述:给你一个整数数组  arr  和两个整数  k  、 threshold  。请你返回长度为  k  且平均值大于等于  threshold  的子数组数目。
- 解题思路:先计算初始窗口(前  k  个元素)的和,判断其平均值是否满足条件,若满足则结果加1。之后滑动窗口,每次窗口滑动时,减去左边离开窗口的元素,加上右边新进入窗口的元素,重新判断窗口内元素的平均值是否满足条件,若满足则结果加1。
- 题目2090. 半径为 k 的子数组平均值
- 题目描述:给你一个整数数组  nums  和一个整数  k  。对于每个满足  i - k >= 0  且  i + k < n  的下标  i  , 计算  (nums[i - k] + nums[i - k + 1] + ... + nums[i + k - 1] + nums[i + k]) / (2 * k + 1)  的值,生成结果数组。如果无法计算这个平均值,则结果数组中的该元素为  -1  。
- 解题思路:先计算初始窗口(长度为  2 * k + 1  )的和,填充对应位置的平均值。之后滑动窗口,每次减去左边离开窗口的元素,加上右边新进入窗口的元素,重新计算并更新对应位置的平均值。

 2. 可变大小滑动窗口

- 题目3. 无重复字符的最长子串
- 题目描述:给定一个字符串  s  ,请你找出其中不含有重复字符的最长子串的长度。
- 解题思路:使用哈希表记录字符最后一次出现的位置。通过左右指针维护滑动窗口,右指针不断右移,当遇到重复字符时,左指针移动到重复字符下一次出现位置的下一位,每次移动更新最长子串的长度。
- 题目76. 最小覆盖子串
- 题目描述:给你一个字符串  s  、一个字符串  t  。返回  s  中涵盖  t  所有字符的最小子串。如果  s  中不存在涵盖  t  所有字符的子串,则返回空字符串  ""  。
- 解题思路:用哈希表  needs  记录  t  中每个字符及其需要的数量。通过左右指针维护滑动窗口,右指针不断右移扩大窗口,当窗口内包含  t  的所有字符时,尝试移动左指针缩小窗口,同时更新最小覆盖子串的长度,直到不能再缩小为止。
- 题目438. 找到字符串中所有字母异位词
- 题目描述:给定两个字符串  s  和  p  ,找到  s  中所有  p  的异位词的子串,返回这些子串的起始索引。异位词指由相同字母重排列形成的字符串(包括相同的字符串)。
- 解题思路:使用两个哈希表,一个记录  p  中字符及其出现次数,另一个记录当前滑动窗口中字符及其出现次数。通过滑动窗口在  s  中移动,当窗口内字符的出现次数与  p  中字符的出现次数完全匹配时,记录当前窗口的起始索引。

3. 滑动窗口与其他数据结构结合

- 题目239. 滑动窗口最大值
- 题目描述:给你一个整数数组  nums  ,有一个大小为  k  的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的  k  个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。
- 解题思路:使用单调队列。单调队列中维护窗口内的元素,并且队头元素始终是窗口内的最大值。当窗口滑动时,移除不在窗口内的元素,同时保持队列的单调性(如果新元素大于队列尾部元素,则移除队列尾部元素,直到不满足该条件)。
- 题目643. 子数组最大平均数 I
- 题目描述:给定  n  个整数,找出平均数最大且长度为  k  的连续子数组,并输出该最大平均数。
- 解题思路:可以先计算初始窗口(前  k  个元素)的和,得到第一个平均数。之后滑动窗口,每次减去左边离开窗口的元素,加上右边新进入窗口的元素,通过新的和计算新的平均数,记录过程中的最大平均数。

4. 其他类型

 - 题目2024. 考试的最大困扰度
- 题目描述:老师出一场由  n  道判断题构成的考试,答案为  'T'  或  'F'  。可以进行最多  k  次操作,每次操作可将一个答案改为  'T'  或  'F'  。要求返回在不超过  k  次操作的情况下,最大连续  'T'  或者  'F'  的数目。
- 解题思路:通过滑动窗口,分别考虑将  F  变成  T  和将  T  变成  F  的情况。在窗口滑动过程中,统计窗口内需要改变的字符数量(即与窗口内较多字符不同的字符数量 ),如果该数量不超过  k  ,则尝试更新最大连续字符的长度;否则移动左指针缩小窗口。
- 题目904. 水果成篮
- 题目描述:农场的一排果树用整数数组  fruits  表示水果种类,只有两个篮子,每个篮子只能装单一类型水果,从任意一棵树开始采摘,每棵树摘一个水果,水果不符合篮子类型时停止采摘,返回可以收集的水果的最大数目。
- 解题思路:使用滑动窗口,窗口内最多包含两种水果类型。右指针移动扩大窗口,当窗口内出现三种水果类型时,左指针移动缩小窗口,直到窗口内恢复为最多两种水果类型,记录过程中窗口的最大长度。

相关文章:

  • WebFlux应用中获取x-www-form-urlencoded数据的六种方法
  • 代码训练day27贪心算法p1
  • Linux Kernel 4
  • spring-boot nacos
  • deepin使用autokey添加微信快捷键一键显隐ctrl+alt+w
  • CExercise_12_单链表面试题_1求链表中间结点的值,判断单链表是否有环
  • 代码随想录训练营第31天 || 56. 合并区间 738. 单调递增的数字
  • gitee基本使用
  • Shell编程之循环语句
  • 【前端样式】使用Flexbox实现经典导航栏:自适应间距与移动端折叠实战
  • MATLAB基本数据类型
  • 如何一键自动提取CAD图中的中心线(如墙体、道路、巷道中心线等)
  • Android常见界面控件、程序活动单元Activity练习
  • LeetCode算法题(Go语言实现)_46
  • 3.2.2.3 Spring Boot配置拦截器
  • C++学习之数据库操作
  • AI日报 - 2025年4月15日
  • 华为OD机试真题——阿里巴巴找黄金宝箱 IV(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • 子串-滑动窗口的最大值
  • 科研软件分享
  • 新干式二尖瓣瓣膜国内上市,专家:重视瓣膜病全生命周期管理
  • 学校食堂饭菜有蛆?举报人遭值班人员辱骂?四川苍溪县教育局回应
  • 最高法专门规范涉企案件审执工作:从源头防止趋利性执法司法
  • 罗马教皇方济各葬礼在梵蒂冈举行
  • 一季度煤价持续下探,多家煤炭巨头营收下滑、净利润降约两成
  • “80后”王建浩履新三沙市委常委、组织部部长、秘书长