一、声明

1.非常感谢东哥(labuladong)分享了**滑动窗口算法框架**;
2.我在理解了东哥的思想后,用Java实现了滑动窗口算法框架,一来方便自己学习,二来方便一些Java小伙伴;
3.再次感谢互联网上的大佬们分享智慧结晶。

二、滑动窗口算法框架

滑动窗口:[left, right)

Map<Character, Integer> window = new HashMap<>();
int size = s.size();
int left = 0, right = 0;
while(right < size) {//增大窗口char c = s.charAt(right);right++;window.put(c, window.getOrDefault(c, 0) + 1);while(window needs shrink) {//缩小窗口char d = s.charAt(left);left++;window.put(d, window.get(d) - 1);}
}

要熟练使用上述框架,需要做到以下几点:
①适用于子串问题;
什么时候缩小窗口取决于题意
比如:题目要求子串不得有重复字符。那么当窗口扩大到包含重复字符时,就需要收缩窗口了。(见三、4
什么时候计算窗口大小(往往窗口大小就是答案)
在window满足题目条件时,就可以计算窗口大小了,即res = right - left;;当然了,题目往往要求最优解,所以要更新res,寻求最优解。
④最好增加个预判:if(sizeS < sizeT) return res;,见三、3

三、秒杀力扣题

0、前言

学习算法框架,就像学习咏春拳,切不可被拳法束缚住,而应该见招拆招。
而要想见招拆招,只能不断熟练拳法,毕竟孰能生巧嘛。

1、76. 最小覆盖子串

class Solution {public String minWindow(String s, String t) {// 需要包含t中的所有字符Map<Character, Integer> need = new HashMap<>();for(char c : t.toCharArray())need.put(c, need.getOrDefault(c, 0) + 1);//滑动窗口Map<Character, Integer> window = new HashMap<>();/*[left, right) 窗口大小:right - left; */int left = 0, right = 0; //初始时,窗口不包含任何元素int valid = 0;   //字符找齐了,valid++;int size = s.length();int minLen = size + 1; //包含t的子串不止1个,要求最小的。int start = 0;  //最优解的起点;while(right < size) {/* 右移动right,扩大窗口,寻找可行解 */char c = s.charAt(right);right++;if(need.containsKey(c)) {//如果是t中的字符,加入到window中window.put(c, window.getOrDefault(c, 0) + 1);if(window.get(c).equals(need.get(c)))valid++;}/* 找到可行解后,右移动left,缩小窗口,进行优化 */int needSize = need.size();while(valid == needSize) {// 不断右移动left,直到valid != needSizec = s.charAt(left);left++;if(need.containsKey(c)) {if(window.get(c).equals(need.get(c)))valid--;window.put(c, window.get(c) - 1);}/* 求最优解 [left - 1, right) */ if(valid != needSize) {if(right - left + 1 < minLen) {start = left - 1;minLen = right - left + 1;}}}}return minLen == size + 1 ? "" : s.substring(start, start + minLen);}
}

注意:window.get(c).equals(need.get(c)),千万不能写成window.get(c) == need.get(c)!!!

2、567. 字符串的排列

class Solution {public boolean checkInclusion(String s1, String s2) {Map<Character, Integer> need = new HashMap<>();for(char c : s1.toCharArray())need.put(c, need.getOrDefault(c, 0) + 1);Map<Character, Integer> window = new HashMap<>();int valid = 0;int left = 0, right = 0;int size1 = s2.length();while(right < size1) {char c = s2.charAt(right);right++;if(need.containsKey(c)) {window.put(c, window.getOrDefault(c, 0) + 1);if(window.get(c).equals(need.get(c)))valid++;}int needSize = need.size();int size2 = s1.length();while(valid == needSize) {if(right - left == size2)return true;c = s2.charAt(left);left++;if(need.containsKey(c)) {if(window.get(c).equals(need.get(c)))valid--;window.put(c, window.get(c) - 1);}}}return false;}
}

和76的代码基本一致,这就是滑动算法框架的魅力:一个模板秒杀一系列的题目(这实际上属于举一反三,毕竟得先理解题意,然后才知道如何应用模板)。

  • 另一种实现方法
class Solution {public boolean checkInclusion(String s1, String s2) {/* 运用滑动窗口算法思想*///按照题目意思,此题的滑动窗口是固定大小;boolean res = false;int size1 = s1.length(), size2 = s2.length();int left = 0, right = left + size1;/* 对s1先排序 */char[] str1 = s1.toCharArray();Arrays.sort(str1);while(right <= size2) {char[] tmp = s2.substring(left, right).toCharArray();Arrays.sort(tmp);if(String.valueOf(tmp).equals(String.valueOf(str1))) {res = true;break;}left++;right = left + size1;}return res;}
}

千万不要局限于模板,虽然上述代码性能不如滑动窗口算法框架,但是代码量少且容易实现。

3、438. 找到字符串中所有字母异位词

class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> res =  new ArrayList<>();int sizeS = s.length(), sizeT = p.length(); if(sizeS < sizeT) return res;Map<Character, Integer> need = new HashMap<>();for(char c : p.toCharArray())need.put(c, need.getOrDefault(c, 0) + 1);int valid = 0;int needSize = need.size();Map<Character, Integer> window = new HashMap<>();int left = 0, right = 0;while(right < sizeS) {char c = s.charAt(right);right++;if(need.containsKey(c)) {window.put(c, window.getOrDefault(c, 0) + 1);if(window.get(c).equals(need.get(c)))valid++;}while(valid == needSize) {if(right - left == sizeT) {res.add(left);}c = s.charAt(left);left++;if(need.containsKey(c)) {if(window.get(c).equals(need.get(c)))valid--;window.put(c, window.get(c) - 1);}}}return res;}
}

和567代码几乎一样。
另外,新增1个预判:if(sizeS < sizeT) return res;

4、3. 无重复字符的最长子串

class Solution {public int lengthOfLongestSubstring(String s) {Map<Character, Integer> window = new HashMap<>();int left = 0, right = 0;int size = s.length();int res = 0;while(right < size) {char c = s.charAt(right);window.put(c, window.getOrDefault(c, 0) + 1);right++;while(window.get(c) > 1) {/* 一旦出现了重复字符,就需要收缩窗口了 */char d = s.charAt(left);left++;window.put(d, window.get(d) - 1);}// [left, right) 窗口中没有重复字符res = Math.max(res, right - left);}return res;}
}

这题并不能生搬硬套华东算法框架,但仍旧是滑动窗口的思想。

/* 伪代码 */
while(right < size) {①统计字符,扩大窗口;(right++)②一旦重复,缩小窗口;(left++)③更新结果:res = Math.max(res, right - left);
}

5、485. 最大连续 1 的个数

class Solution {public int findMaxConsecutiveOnes(int[] nums) {int left = 0, right = 0;int res = 0;while(right < nums.length) {//扩大窗口while(right < nums.length && nums[right] == 1) right++;//遇到了0或者已经超出边界,即不能再扩大了;res = Math.max(res, right - left);//缩小窗口right++; //跳过0left = right;}return res;}
}

虽然这道题看上去很像滑动窗口的题目,但是这种简单题反而用直觉的方法更好(不易出错,毕竟杀鸡焉用牛刀!)

6、后言

(1)最好不要奢望无脑套用框架刷算法题,而之所以学习些算法框架(或者说套路)是因为多积累一种解题思路往往多了一些机会去秒杀算法题。
(2)本文的滑动窗口算法框架在性能方面并不是最优的(毕竟套用框架省了脑力,多半会牺牲性能)。

滑动窗口算法框架(Java版)秒杀力扣题(76、567、438、3、485)相关推荐

  1. 滑动窗口算法(C语言版讲解)

    滑动窗口算法(C语言讲解) 滑动窗口算法主要用于解决字符串查找对应排序的题型. 算法的基本思路 1.辅助算法 :快慢指针 由于要运用快慢指针的思想,这里读者需要先了解快慢指针. typedef str ...

  2. 三角形的最大周长Java版(力扣)

    三角形的最大周长 给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的.面积不为零的三角形的最大周长. 如果不能形成任何面积不为零的三角形,返回 0. 示例 1: 输入:[2,1,2] ...

  3. 列表左右箭头滑动_我写了一套框架,把滑动窗口算法变成了默写题

    读完本文,你可以去力扣拿下如下题目: 76.最小覆盖子串 567.字符串的排列 438.找到字符串中所有字母异位词 3.无重复字符的最长子串 ----------- 鉴于前文 二分搜索框架详解 的那首 ...

  4. 滑动窗口算法通用思想

    文章目录 一.最小覆盖子串 二.找到字符串中所有字母异位词 三.无重复字符的最长子串 最后总结 本文详解「滑动窗口」这种高级双指针技巧的算法框架,带你秒杀几道难度较大的子字符串匹配问题: 最小覆盖子串 ...

  5. JS:滑动窗口算法 (上集)

    建议先读文章,本文解决一类最难掌握的双指针技巧:滑动窗口技巧. 难度在于各种细节问题,比如:如何向窗口中添加新元素,如何缩小窗口,在窗口滑动的哪个阶段更新结果. 技术: 用到的数据结构--哈希表(字典 ...

  6. Java实现滑动窗口算法

    Java实现滑动窗口算法 滑动窗口算法 滑动窗口应用实例 基本实例 断路器怎么识别断路器的状态 代码实现 滑动窗口算法 思想不滑坡 方法总比困难多 滑动窗口协议(Sliding Window Prot ...

  7. Java算法-滑动窗口算法(Sliding Window)(十)

    滑动窗口 滑动窗口概念不仅存在于数据链路层,也存在于传输层,两者有不同的协议,但基本原理是相近的.其中一个重要区别是,一个是针对于帧的传送,另一个是字节数据的传送. 滑动窗口(Sliding wind ...

  8. 滑动窗口算法用法及实题详解

    在力扣常用解题法中,我们常常会看到这些: 滑动窗口 双指针 快慢指针/ 链表题目 原地链表翻转 区间合并 无序限定范围的数组元素查找O(N) BFS 树的DFS DFS/递归/回溯法 双堆模式 2分变 ...

  9. Python数据结构与算法篇(四)-- 滑动窗口算法

    数组和链表代表着计算机最基本的两种存储形式:顺序存储和链式存储,所以他俩可以算是最基本的数据结构.数组是一种基础数据结构,可以用来处理常见的排序和二分搜索问题,典型的处理技巧包括双指针.滑动窗口等,数 ...

最新文章

  1. BZOJ 1923: [Sdoi2010]外星千足虫
  2. 动态卷积系列工作的基础:CondCov按需定制的卷积权重
  3. MathML + MathJax在网页中插入公式
  4. 传统多线程之前如何共享数据
  5. 莫名其妙的突然想学日语了, 开始接触日语,希望能坚持下去。
  6. 多模块Maven工程单独打包某一模块工程
  7. access对比数据_数据仓库系列之数据质量管理
  8. 工业交换机与普通商用交换机的对比详解
  9. Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍
  10. SecureCRT护眼设置
  11. 2021年美食类短视频及直播营销趋势洞察
  12. Linux笔记-inode基本概念
  13. weihan talk
  14. javascript Control flow(控制语句)
  15. VALSE学习(九):物体检测进展
  16. 微分方程数值解法的matlab程序
  17. 计算机PPT在哪打开,电脑自带ppt在哪
  18. android仿咸鱼底部导航栏,Flutter沉浸式状态栏/AppBar导航栏/仿咸鱼底部凸起导航栏效果...
  19. ps如何设置滚动鼠标放大和缩小图像
  20. 零基础如何学习 Web 安全?

热门文章

  1. 模块加载及第三方包:Node.js模块化开发、系统模块、第三方模块、package.json文件、Node.js中模块的加载机制、开发环境与生产环境、cookie与session
  2. 华为鸿蒙生态伙伴峰会,华为鸿蒙生态加速 市场相关板块再度活跃
  3. mysql data目录 清空_Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~...
  4. 软件项目管理作业——软件中的创新点
  5. 数字城市的建设有哪些意义?如何构建数字城市?
  6. {spring.cloud.client.ipAddress}
  7. FCU1104双网数采网关在碳中和目标下的在线能耗监测方案
  8. 赛码网输入注意事项 Python
  9. 电商--订单支付中存在的问题以及思考
  10. 迷茫是短暂的,人生是漫长的