文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【LeetCode算法成长之路】滑动窗口算法总结与经典题目分析

2023-09-08 17:25

关注

前言

在这里插入图片描述

本文小新为大家带来 滑动窗口算法 相关知识,经过对滑动窗口算法类题目的总结,为大家分享滑动窗口算法概述(包括:滑动窗口算法思想滑动窗口算法使用场景滑动窗口算法使用思路),滑动窗口算法代码模板,以及两个经典例题(长度最小的子数组最小覆盖子串),帮助大家更好的理解与掌握滑动窗口算法~

不积跬步,无以至千里;不积小流,无以成江海。每天进步一点点,在成为强者的路上,小新与大家共同成长!

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)


目录

文章标题

在这里插入图片描述

一、滑动窗口算法概述

1️⃣滑动窗口算法思想

滑动窗口算法是在给定特定窗口大小(当然也可以是动态可变窗口)的数组或者字符串上进行操作的算法,该算法主要的用途就是在于将嵌套循环时间复杂度的效率优化成为线性时间复杂度。简而言之,滑动窗口算法在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度,从而也达到降低了循环的嵌套深度。

从字面意思上理解的话:

滑动: 说明这个窗口是移动的,也就是移动是按照一定方向来的。

窗口: 窗口大小并不是固定的,可以不断扩容直到满足一定的条件;也可以不断缩小,直到找到一个满足条件的最小窗口;当然也可以是固定大小。

一般来讲,滑动窗口算法需要借助两个指针left与right来完成。

2️⃣滑动窗口算法使用场景

一般可以使用滑动窗口算法的题目中会包含以下关键词:

例如: 长度最小的子数组

3️⃣滑动窗口算法使用思路

滑动窗口算法使用思路(寻找最长):

滑动窗口算法使用思路(寻找最短):

二、滑动窗口算法代码模板

寻找最长问题的模板:

// left,right指针分别指向窗口的左边与后边位置// result用来保存计算的结果,该结果需要满足一定的条件// baseResult用来保存需要求得的结果:最长的长度初始化left,right, result, bestResult;while(右指针没有到结尾) {    窗口扩大,加入right对应元素,更新当前result;    while(result不满足要求){        窗口缩小,移除left对应元素,left右移;    }    更新最优结果到bestResult;    right++;}return bestResult;

寻找最短问题的模板:

// left,right指针分别指向窗口的左边与后边位置// result用来保存计算的结果,该结果需要满足一定的条件// baseResult用来保存需要求得的结果:最短的长度初始化left,right, result, bestResult;while(右指针没有到结尾){    窗口扩大,加入right对应元素,更新当前result;    while(result满足要求){        更新最优结果bestResult;        窗口缩小,移除left对应元素,left右移;    }    right++;}return bestResult;

三、例题1:长度最小的子数组

1️⃣题目描述

LeetCode209. 长度最小的子数组

给定一个含有 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 <= 1091 <= nums.length <= 1051 <= nums[i] <= 105

2️⃣思想概述

有了这两个条件我们就可以套用寻找最短问题的模板来求解问题。

3️⃣代码实现

class Solution {    public int minSubArrayLen(int target, int[] nums) {        int left = 0;        int right = 0;        int sum = 0;        int minLength = Integer.MAX_VALUE;        // 右指针没有到结尾        while(right < nums.length){            sum += nums[right];            // sum满足条件,更新最优结果,并尝试向右移动left指针来缩小窗口            while(sum >= target){                minLength = Math.min(minLength, right - left + 1);                sum -= nums[left];                left++;             }            right++;        }        return minLength == Integer.MAX_VALUE ? 0 : minLength;    }}

四、例题2:最小覆盖子串

上面的题目还是比较简单的,如果掌握了滑动窗口算法的话,下面我们来看一个困难级别的题目来体验一下。

1️⃣题目描述

LeetCode76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"输出:"BANC"解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"输出:"a"解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = "a", t = "aa"输出: ""解释: t 中两个字符 'a' 均应包含在 s 的子串中,因此没有符合条件的子字符串,返回空字符串。

提示:

m == s.lengthn == t.length1 <= m, n <= 105s 和 t 由英文字母组成

2️⃣思想概述

有了这两个条件,通过套用寻找最短问题的模板来求解该问题也是没太大难度的。这题的难点在于我们如何来判断字符串s的某个子串能够涵盖字符串 t 中的所有字符。

我们可以用一个哈希表来表示字符串 t 中所有的字符以及它们出现的个数,用另外一个哈希表动态维护窗口中所有的字符以及它们出现的个数,如果这个动态表中包含 t 的哈希表中的所有字符,并且对应的个数都不小于 t 的哈希表中各个字符的个数,那么当前的窗口是可行的(对于该判断我们可以专门写一个方法来实现)。

3️⃣代码实现

class Solution {    // 用来动态维护窗口中子串的所有字符以及它们出现的个数    Map<Character,Integer> num_s = new HashMap<Character,Integer>();    // 用来保存字符串 t 中所有的字符以及它们出现的个数    Map<Character,Integer> num_t = new HashMap<Character,Integer>();    public String minWindow(String s, String t) {        // 先获取字符串 t 中所有的字符以及它们出现的个数        for(int i = 0; i < t.length(); i++){            char c = t.charAt(i);            num_t.put(c, num_t.getOrDefault(c, 0) + 1);        }        int left = 0;        int right = 0;        int res_l=-1,res_r=-1;        int minLength = Integer.MAX_VALUE;        // 右指针没有到结尾        while(right < s.length()){            char c2 = s.charAt(right);            if(num_t.containsKey(c2)){                num_s.put(c2, num_s.getOrDefault(c2, 0) + 1);            }            // 判断当前的子串是否包含字符串t,满足条件的话,更新最优结果,并尝试向右移动left指针来缩小窗口            while(check() && left <= right){                if(right - left +1<minLength){                    res_l = left;                    res_r = right;                    minLength = right - left +1;                }                char c3 = s.charAt(left);                if(num_s.containsKey(c3)){                    num_s.put(c3, num_s.getOrDefault(c3, 0) - 1);                }                left++;            }            right++;        }                if(minLength == Integer.MAX_VALUE){            return "";        }else{            return s.substring(res_l, res_r+1);        }        // 上边这段代码的简写        // return minLength == Integer.MAX_VALUE ? "" : s.substring(res_l, res_r+1);            }    // 用来判断某子串是否涵盖t中所有字符的方法    public boolean check(){        Iterator iter = num_t.entrySet().iterator();        while(iter.hasNext()){            Map.Entry entry = (Map.Entry) iter.next();            Character key = (Character) entry.getKey();            Integer val = (Integer) entry.getValue();            if(num_s.getOrDefault(key, 0) < val){                return false;            }        }        return true;    }}

后记

在这里插入图片描述

本文为大家分享了 滑动窗口算法的思想,并且 为大家梳理了用滑动窗口算法解决问题的代码模板,最后通过两个经典例题(长度最小的子数组最小覆盖子串)来帮助大家更好的理解与掌握滑动窗口算法~

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~

来源地址:https://blog.csdn.net/qq_42146402/article/details/129890383

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯