什么是「滑动窗口算法」(sliding window algorithm),有哪些应用场景?
今天是算法数据结构专题的第2篇文章,我们一起来学习一下「滑动窗口算法」。
前言
最近刷到leetCode里面的一道算法题,里面有涉及到Sliding windowing算法,因此写一篇文章稍微总结一下
算法题介绍
没有重复字符的子字符的最大长度:给一个字符串,获得没有重复字符的最长子字符的长度
例子:
输入:"abcabcbb"
输出:3
解释:因为没有重复字符的子字符是'abc',所以长度是3
解法1:暴力解法
public class Solution {//时间复杂度高O(n3)
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
//遍历所有的子字符串,记录没有重复字母的子字符串的最大的长度
//获取子字符串时,使用两个标签,分别代表子字符串的开头和结尾
for (int i = 0; i < n; i++)
for (int j = i + 1; j <= n; j++)
//当子字符串没有重复字母时,ans记录最大的长度
if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
return ans;
}
//判断该子字符串是否有重复的字母
public boolean allUnique(String s, int start, int end) {
//HashSet实现了Set接口,它不允许集合中出现重复元素。
Set<Character> set = new HashSet<>();
for (int i = start; i < end; i++) {
Character ch = s.charAt(i);
if (set.contains(ch)) return false;
set.add(ch);
}
return true;
}
}
分析
时间复杂度:O(n3)
.
解法2:滑动窗口算法
通过使用HashSet作为一个滑动窗口,检查一个字符是否已经存在于现有的子字符中只需要O(1).
滑动窗口经常作为一个抽象的概念来处理数组/字符串问题。窗口代表着一组数据/字符串元素,通过开头和结尾的索引来定义窗口。
public class Solution {//时间复杂度O(2n)
//滑动窗口算法
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {//窗口的左边是i,右边是j,下列算法将窗口的左右移动,截取出其中一段
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){//如果set中不存在该字母,就将j+1,相当于窗口右边向右移动一格,左边不动
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);//记录目前存在过的最大的子字符长度
}
else {//如果set中存在该字母,则将窗口左边向右移动一格,右边不动,直到该窗口中不存在重复的字符
set.remove(s.charAt(i++));
}
}
return ans;
}
}
分析
时间复杂度:O(2n)
。在最差的情况下,每个字符将会被访问两次
解法3:优化的滑动窗口算法
上面的滑动窗口算法最多需要2n的步骤,但这其实是能被优化为只需要n步。我们可以使用HashMap定义字符到索引之间的映射,然后,当我们发现子字符串中的重复字符时,可以直接跳过遍历过的字符了。
public class Solution {//时间复杂度o(n)
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
//使用hashmap记录遍历过的字符的索引,当发现重复的字符时,可以将窗口的左边直接跳到该重复字符的索引处
Map<Character, Integer> map = new HashMap<>(); // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {//j负责向右边遍历,i根据重复字符的情况进行调整
if (map.containsKey(s.charAt(j))) {//当发现重复的字符时,将字符的索引与窗口的左边进行对比,将窗口的左边直接跳到该重复字符的索引处
i = Math.max(map.get(s.charAt(j)), i);
}
//记录子字符串的最大的长度
ans = Math.max(ans, j - i + 1);
//map记录第一次遍历到key时的索引位置,j+1,保证i跳到不包含重复字母的位置
map.put(s.charAt(j), j + 1);
}
return ans;
}
}
分析
时间复杂度:O(n)
滑动窗口算法总结
- 滑动窗口算法可以用以解决数组/字符串的子元素问题
- 滑动窗口算法可以将嵌套的for循环问题,转换为单循环问题,降低时间复杂度
什么是「滑动窗口算法」(sliding window algorithm),有哪些应用场景?的更多相关文章
- 滑动窗口协议(Sliding Window Protocol)
滑动窗口协议(Sliding Window Protocol),属于TCP协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生.该协议允许发送方在停止并等待确认前发送多个数据分组.由于发送方 ...
- 滑动窗口的中位数 · Sliding Window Median
[抄题]: 给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中滑动这个窗口,找到数组中每个窗口内的中位数.(如果数组个数是偶数,则在该窗口排序数字后,返回第 N/2 个数字 ...
- 洛谷——P1886 滑动窗口|| POJ——T2823 Sliding Window
https://www.luogu.org/problem/show?pid=1886#sub || http://poj.org/problem?id=2823 题目描述 现在有一堆数字共N个数字( ...
- Sentinel滑动窗口算法
在前面搞清楚了Sentinel的使用后,大致理了一下Sentinel的责任链,搞清楚了这个,基本就已经梳理清楚sentinel-core模块的大部分内容,顺着这条链路可以继续梳理很多东西. 知其然.知 ...
- 【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(上)
承接上文 承接之前的[精华推荐 |[算法数据结构专题]「延时队列算法」史上非常详细分析和介绍如何通过时间轮(TimingWheel)实现延时队列的原理指南],让我们基本上已经知道了「时间轮算法」原理和 ...
- ST算法 Sliding Window algorithm template
ST算法(Sliding Window):A easy way to slove the substring problems algorithm template to slove substrin ...
- 精华推荐 |【算法数据结构专题】「延时队列算法」史上非常详细分析和介绍如何通过时间轮(TimingWheel)实现延时队列的原理指南
时间轮的介绍 时间轮(TimeWheel)是一种实现延迟功能(定时器)的精妙的高级算法,其算法应用范围非常广泛,在Java开发过程中常用的Dubbo.Netty.Akka.Quartz.ZooKeep ...
- [LeetCode] Sliding Window Median 滑动窗口中位数
Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...
- 滑动窗口(Sliding Window)技巧总结
什么是滑动窗口(Sliding Window) The Sliding Problem contains a sliding window which is a sub – list that run ...
- LC算法技巧总结(二):双指针和滑动窗口技巧
我把双指针技巧再分为两类,一类是「快慢指针」,一类是「左右指针」.前者解决主要解决链表中的问题,比如典型的判定链表中是否包含环:后者主要解决数组(或者字符串)中的问题,比如二分查找. 一.快慢指针的常 ...
随机推荐
- 6k Star!B站、滴滴、小红书都在用的网站防火墙
你有网站么?你担心网站被黑客攻击么?你知道如何抵御来自黑客的攻击吗? 据称互联网上有 30% 的流量都来自于恶意攻击.做过 Web 开发或者有过建站经验的朋友对 SQL 注入.CC 攻击.XSS.We ...
- iOS程序生命周期流程
盛年不重来,一日难再晨.及时宜自勉,岁月不待人. iOS系统资源是有限的,合理的去配置应用程序的运行状态以及了解app的生命周期对于大多数开发者来说是很重要的一件事情!在后台进行运行时app会受到 ...
- dev-c++ 使用教程
Dev C++ 支持单个源文件的编译,如果你的程序只有一个源文件(初学者基本都是在单个源文件下编写代码),那么不用创建项目,直接运行就可以:如果有多个源文件,才需要创建项目. 一.新建源文件 1.通过 ...
- Linux笔记03: Linux常用命令_3.1命令的基本格式
3.1命令的基本格式 3.1.1 命令提示符 [root@localhost ~]# 这就是Linux系统的命令提示符.各部分含义如下: ●[]:这是提示符的分隔符号,没有特殊含义. ●root:显示 ...
- 理解 Paimon changelog producer
介绍 目的 Chaneglog producer 的主要目的是为了在 Paimon 表上产生流读的 changelog, 所以如果只是批读的表是可以不用设置 Chaneglog producer 的. ...
- 华企盾DSC客户端图标不显示常见处理方法
1.检查是否启用了360桌面.猎豹桌面之类的(兼容腾讯桌面),打强制显示客户端图标的补丁 2.是否被杀毒软件查杀 3.用Autoruns查看explorer项图标那一栏前10个是否有我们图标没有的话把 ...
- 使用Mybatis自定义插件实现不侵入业务的公共参数自动追加
背景 后台业务开发的过程中,往往会遇到这种场景:需要记录每条记录产生时间.修改时间.修改人及添加人,在查询时查询出来. 以往的做法通常是手动在每个业务逻辑里耦合上这么一块代码,也有更优雅一点的做法是写 ...
- 万界星空科技QMS质量管理系统
QMS(Quality Management System)质量管理系统是五大基础系统之一,在工业企业中被广泛的应用,在质量策划.生产过程质量监督.体系审核和文档管理等业务上发挥着不可替代的作用. 一 ...
- 常用API之IP定位地区
常用API之IP定位地区 高德地图API https://lbs.amap.com/api/webservice/guide/api/ipconfig 百度地图API https://lbsyun.b ...
- 用Spring Boot 3.2虚拟线程搭建静态文件服务器有多快?
Spring Boot 3.2 于 2023 年 11 月大张旗鼓地发布,标志着 Java 开发领域的一个关键时刻.这一突破性的版本引入了一系列革命性的功能,包括: 虚拟线程:利用 Project L ...