今天是算法数据结构专题的第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),有哪些应用场景?的更多相关文章

  1. 滑动窗口协议(Sliding Window Protocol)

    滑动窗口协议(Sliding Window Protocol),属于TCP协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生.该协议允许发送方在停止并等待确认前发送多个数据分组.由于发送方 ...

  2. 滑动窗口的中位数 · Sliding Window Median

    [抄题]: 给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中滑动这个窗口,找到数组中每个窗口内的中位数.(如果数组个数是偶数,则在该窗口排序数字后,返回第 N/2 个数字 ...

  3. 洛谷——P1886 滑动窗口|| POJ——T2823 Sliding Window

    https://www.luogu.org/problem/show?pid=1886#sub || http://poj.org/problem?id=2823 题目描述 现在有一堆数字共N个数字( ...

  4. Sentinel滑动窗口算法

    在前面搞清楚了Sentinel的使用后,大致理了一下Sentinel的责任链,搞清楚了这个,基本就已经梳理清楚sentinel-core模块的大部分内容,顺着这条链路可以继续梳理很多东西. 知其然.知 ...

  5. 【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(上)

    承接上文 承接之前的[精华推荐 |[算法数据结构专题]「延时队列算法」史上非常详细分析和介绍如何通过时间轮(TimingWheel)实现延时队列的原理指南],让我们基本上已经知道了「时间轮算法」原理和 ...

  6. ST算法 Sliding Window algorithm template

    ST算法(Sliding Window):A easy way to slove the substring problems algorithm template to slove substrin ...

  7. 精华推荐 |【算法数据结构专题】「延时队列算法」史上非常详细分析和介绍如何通过时间轮(TimingWheel)实现延时队列的原理指南

    时间轮的介绍 时间轮(TimeWheel)是一种实现延迟功能(定时器)的精妙的高级算法,其算法应用范围非常广泛,在Java开发过程中常用的Dubbo.Netty.Akka.Quartz.ZooKeep ...

  8. [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 ...

  9. 滑动窗口(Sliding Window)技巧总结

    什么是滑动窗口(Sliding Window) The Sliding Problem contains a sliding window which is a sub – list that run ...

  10. LC算法技巧总结(二):双指针和滑动窗口技巧

    我把双指针技巧再分为两类,一类是「快慢指针」,一类是「左右指针」.前者解决主要解决链表中的问题,比如典型的判定链表中是否包含环:后者主要解决数组(或者字符串)中的问题,比如二分查找. 一.快慢指针的常 ...

随机推荐

  1. 使用DHorse发布SpringBoot项目到K8S

    前言 在介绍DHorse的操作之前,先来介绍一下使用k8s发布应用的步骤,以SpringBoot应用为例进行说明. 1.首先从代码仓库下载代码,比如GitLab: 2.接着进行构建,比如使用Maven ...

  2. Modbus转PROFINET网关助力电子天平与西门子PLC无缝对接

    背景: 在制药.食品科学和其他行业中,电子天平被广泛用于质量控制和分析实验.它们可以用于检测样品的净重.含量和浓度,并用于监测产品的制造过程. 常州某反应器公司实验室近期采购一批电子天平,现需要把电子 ...

  3. Jenkins从Ubuntu迁移至AlmaLinux问题及相关解决记录

    相关背景 之前在Ubuntu平台上搭建了Jenkins(在Ubuntu机器上使用war包安装Jenkins),现在由于一些需求,需要将系统迁移到AlmaLinux平台.由于AlmaLinux属于Cen ...

  4. 从物理机到K8S:应用系统部署方式的演进及其影响

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. 概述 随着科技的进步,软件系统的部署架构也在不断演进,从以前传统的物理机到虚拟机.Docker和Kubernetes,我们 ...

  5. 洛谷3521 [POI2011]ROT-Tree Rotations(线段树合并)

    题意:给定一颗有 n 个叶节点的二叉树.每个叶节点都有一个权值pi​(注意,根不是叶节点),所有叶节点的权值构成了一个1∼n 的排列.对于这棵二叉树的任何一个结点,保证其要么是叶节点,要么左右两个孩子 ...

  6. MINA框架

    一.小程序MINA框架分为三个部分: 有 View(视图层).App Service(逻辑层)和 Natice(系统层). 1.View(视图层) 视图层包含了小程序多个页面.每个页面都有WXML文件 ...

  7. [NOI online2022普及A] 王国比赛

    题目描述 智慧之王 Kri 统治着一座王国. 这天 Kri 决定举行一场比赛,来检验自己大臣的智慧. 比赛由 \(n\) 道判断题组成,有 \(m\) 位大臣参加.现在你已经知道了所有大臣的答题情况, ...

  8. libgdx摄像头的移动

    要知道,做一个游戏,摄像头是必不可少的.接下来,我将讲解libgdx里面摄像头的移动 2d摄像头OrthographicCamera也叫做正交相机 结果展示: 按上下左右是可以移动的 Orthogra ...

  9. 2023河南省第五届“金盾信安杯”CRYPTO MISC 复现

    MISC 来都来了 题目 我的解答: 给了一个加密压缩包,010查看发现是伪加密,修改如下两部分: 头部和尾部的09分别改为00 然后解压得到: 尝试base64解码得到很零散的结果..大眼一看不知道 ...

  10. 确定了-C#是2023年度的编程语言!

    大家好,我是沙漠尽头的狼.在朋友圈看到桂素伟大佬发的喜讯截图,站长赶紧翻译向大家报喜,确定了-C#是2023年度的编程语言! 在TIOBE指数的历史上,C#首次获得了年度编程语言的奖项.祝贺!二十多年 ...