IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 滑动窗口模板 -> 正文阅读

[数据结构与算法]滑动窗口模板

基本思想

滑动窗口是双指针技巧的一种,定义两个指针,left 和 right,用 left,right 表示滑动窗口的左边界和右边界,通过改变left,right来扩展和收缩滑动窗口,可以想象成一个窗口在滑动。这就是滑动窗口的基本思想

使用滑动窗口前需要思考以下4个点:

  1. 增大窗口时,要更新哪些数据?
  2. 什么时候停止增大窗口,开始缩小窗口?
  3. 缩小窗口时,要更新哪些数据?
  4. 最后的结果在增大窗口时更新,还是缩小窗口时更新?

写滑动窗口算法前一定要明白以上4个点,不然根本写不出算法!!!

算法模板

抽象算法框架,具体还是得根据题干要求,慢慢补充里面的血肉之躯。

int left = 0, right = 0;

while (right < s.size()) {
    window.add(s[right]);
    right++;
    
    while (满足缩小窗口条件) {
        window.remove(s[left]);
        left++;
    }
}

一定要明白,滑动窗口算法在写代码中,代码是符合对称结构的。

应用场景

在子串和子数组中应用特别广泛:

  • 1、字符串。在一个字符串中找出符合另一个字符串的子串
  • 2、子数组。在一个数组中找到满足条件的子数组

例题应用

子串

LeetCode 3题 - 无重复字符的最长子串

class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        int left = 0;
        int right = 0;
        int res = 0;
        HashMap<Character,Integer> window = new HashMap<>();
        //增大窗口
        while (right < s.length()) {
            char c = s.charAt(right);
            window.put(c,window.getOrDefault(c,0)+1);
            right++;
            //缩小窗口
            while(window.get(c)>1){              
                char c1 = s.charAt(left);
                window.put(c1,window.get(c1)-1);
                left++;
            }
             //更新结果
            res = Math.max(right-left,res);
        }
        
        return res;
    }
}

LeetCode 76题 - 最小覆盖子串

class Solution {
    public String minWindow(String s, String t) {

        if (s.length() < t.length()) {
            return "";
        }

        //滑动窗口
        HashMap<Character,Integer> window = new HashMap<>();
        
        //辅助工具
        HashMap<Character,Integer> need = new HashMap<>();
        for (char c : t.toCharArray()) {
            need.put(c,need.getOrDefault(c,0)+1);
        }

        int left = 0;
        int right = 0;

		//存储结果
        int start = 0;
        int end = 0;
        int minLen = Integer.MAX_VALUE;

        //记录 window 中已经有多少字符符合要求了
        int match = 0;

        while (right < s.length()) {
            char c = s.charAt(right);
            window.put(c,window.getOrDefault(c,0)+1);
            if((window.get(c)).equals(need.get(c))){
                match++;
            }
            right++;
            //缩小窗口
            while(match==need.size()){
                //更新结果
                if(right-left<minLen){
                    start = left;
                    end = right;
                    minLen = right-left;
                }
                char c1 = s.charAt(left);
                window.put(c1,window.get(c1)-1);
                if(need.containsKey(c1)){
                    if(window.get(c1)<need.get(c1)){
                        match--;
                    }
                }
                left++;
            }
        }
        return minLen==Integer.MAX_VALUE?"":s.substring(start, end);
    }
}

LeetCode 438题 - 找到字符串中所有字母异位词

class Solution {

    public List<Integer> findAnagrams(String s, String p) {

        //滑动窗口
        HashMap<Character,Integer> window = new HashMap<>();
        //辅助工具
        HashMap<Character,Integer> need = new HashMap<>();
        for (char c : p.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0) + 1);
        }

        int left = 0;
        int right = 0;

		//记录 window 中已经有多少字符符合要求了
        int match = 0;

        //存储结果
        List<Integer> res = new ArrayList<>();

        while (right < s.length()) {
            char c = s.charAt(right);
            window.put(c, window.getOrDefault(c, 0) + 1);
            if(need.containsKey(c)){  
                if(window.get(c).equals(need.get(c))){
                    match++;
                }
            }
            right++;
            while (match == need.size()) {
                //更新结果
                if (right - left == p.length()) {
                    res.add(left);
                }
                char c1 = s.charAt(left);
                window.put(c1,window.get(c1)-1);
                if (need.containsKey(c1)) {
                    if (window.get(c1) < need.get(c1)) {
                        match--;
                    }
                }
                left++;
            }
        }
        return res;
    }
}

LeetCode 567题 - 字符串的排列

class Solution {
    public boolean checkInclusion(String s1, String s2) {

        //滑动窗口
        HashMap<Character,Integer> window = new HashMap<>();
        //辅助
        HashMap<Character,Integer> need = new HashMap<>();
        for (char c : s1.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0) + 1);
        }

        int left = 0;
        int right = 0;

		//记录 window 中已经有多少字符符合要求了
        int match = 0;
        
        while (right < s2.length()) {
            char c = s2.charAt(right);
            window.put(c, window.getOrDefault(c, 0) + 1);
            if (need.containsKey(c)) {
                if(window.get(c).equals(need.get(c))){
                    match++;
                }
            }
            right++;
            while (match == need.size()) {
                //更新结果
                if (right - left == s1.length()) {
                    return true;
                }
                char c1 = s2.charAt(left);
                window.put(c1, window.get(c1) - 1);
                if(need.containsKey(c1)){ 
                    if (window.get(c1) < need.get(c1)) {
                        match--;
                    }
                }
                left++;
            }
        }
        return false;
    }
}

子数组

LeetCode 209题 - 长度最小的子数组

class Solution {
    public int minSubArrayLen(int target, int[] nums) {

        int left = 0;
        int right = 0;
        int sum = 0;
        int minLen = Integer.MAX_VALUE;

        while (right < nums.length) {
            int num = nums[right];
            sum += num;
            right++;
            while (sum >= target) {
                //更新结果
                if (right - left < minLen) {
                    minLen = right - left;
                }
                int num1 = nums[left];
                sum -= num1;
                left++;
            }
        }
        return minLen==Integer.MAX_VALUE?0:minLen;
    }
}

剑指offer - 和为S的连续正数序列

class Solution {
    public int[][] findContinuousSequence(int target) {

        //存储结果
        List<int[]> res = new ArrayList<>();

        int left = 1;//注意
        int right = 1;//注意
        int sum = 0;
        //为什么是target/2 +1?其实只要求target前半部分就可以了,后面部分的target加起来一定是大于target的。不加1会存在漏解的情况
        while (right <= (target / 2 + 1)) {
            int num = right;
            sum += right;
            right++;
            while (sum >= target) {
                //更新结果
                if (sum == target) {
                    int[] temp = new int[right - left];
                    for (int i = 0; i < temp.length; i++) {
                        temp[i] = left + i;
                    }
                    res.add(temp);
                }
                int num1 = left;
                sum -= num1;
                left++;
            }
        }
        return res.toArray(new int[res.size()][]);
    }
}

参考资料

我写了套框架,把滑动窗口算法变成了默写题
滑动窗口算法框架

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 12:18:53  更:2021-08-19 12:21:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:45:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码