优选算法的智慧之光:滑动窗口专题(二)



专栏:算法的魔法世界
个人主页:手握风云
目录
一、例题讲解
1.1. 最大连续1的个数 III
1.2. 找到字符串中所有字母异位词
1.3. 串联所有单词的子串
1.4. 最小覆盖子串
一、例题讲解
1.1. 最大连续1的个数 III

题目要求是二进制数组,也就是数组中的元素只有0和1。最多翻转k个0,而不是恰好,也就是当数组中0的个数小于k,就不用真的去翻转k个0。
如果我们按照题目要求解题,代码会非常不好写,因为我们还要去翻转0。我们可以转化一下,我们从数组当中找出一个最长子数组,并且这个子数组中0的个数不超过k个,这样我们就不用再去进行翻转0的操作。
我们先来思考一下暴力枚举:我们先固定数组当中的第一个元素为起点,然后向后移动,当子数组中0的个数超过k就停止(如下图所示)。我们还需要一个额外的变量zero来统计0的个数。

接下来根据暴力枚举进行优化。先定义left和right指针指向数组的第一个元素,然后让right指针向后移动。直到left与right所构成的子数组中0的个数大于k。根据暴力枚举的思路,接下来就让left指针也向右一位,right指针也要回退再向右移动。在这段区间内,right还是依旧走到我们原来的位置。

通过上面的分析,我们发现right指针不需要回退,让left指针直接越过这段区域。这时我们就会发现同向双指针,也就是利用滑动窗口来解决。步骤还是“进窗口→判断→出窗口→更新结果”。进窗口,当right遇到1的时候,无视;遇到0,zero+1。判断,当zero>k时,left向右移动,完成出窗口的操作。

public class Solution {public int longestOnes(int[] nums, int k){int ret = 0;for (int left = 0,right = 0,zero = 0;right < nums.length; right++){if(nums[right] == 0) zero++;//进窗口while(zero > k){//判断if(nums[left++] == 0) zero--;//出窗口ret = Math.max(ret,right-left+1);}}return ret;}
}
1.2. 找到字符串中所有字母异位词

我们看下上面的示例1,p可以重新排列为abc、acb、bac、bca、cab、cba。s中的索引则为[0,2]、[6,8],最终输出结果为[0,6]。
首先我们需要思考如何判断两个字符串为异位词,我们可以利用两个哈希表来统计字符串中字母出现的个数,如果个数相等,则两个字符串为异位词。我们先来思考暴力解法:先把字符串p丢进hash1中,然后从字符串s中找到长度与p相等的子串丢进hash2中,并统计子串中出现的字母个数。

其实我们从上图中,很容易想到如何对暴力解法进行优化:统计完第一个子串,让里面的字符开始进出哈希表。就像窗口一样从头到尾,并且滑动窗口的长度是固定的,与p的长度相等。
然后我们就可以利用滑动窗口的步骤来解题:进窗口,把字符丢进hash2中;判断,当窗口的长度大于p的长度时,就要进行出窗口的操作;最后检查两个哈希表中的字符数量是否一致,更新结果。

由于题目当中的字符串仅包含小写字母,所以我们可以定义一个大小为26的数组来与哈希表判断是否相等,还需要判断进出窗口,这样时间复杂度就为26+n→。但如果我们遇到更难的题目就可能会超时,我们还需要对最后的更新做优化。
我们再额外定义一个变量来统计“有效字符”的个数,这个“有效字符”指的是p中的字符。进入后,如果hash2中的有效字符小于hash1中的字符,则count++;出去前,我们需要检查出去的字符是否等于hash1中的字符,则出去的是有效字符。进出窗口的同时维护count的大小。
class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> ret = new ArrayList<Integer>();char[] ss = s.toCharArray();char[] pp = p.toCharArray();int[] hash1 = new int[26];//统计p中每一个字符出现的个数for(char ch : pp) hash1[ch - 'a']++;int[] hash2 = new int[26];//统计窗口中字符出现的个数for (int left = 0,right = 0,count = 0;right < s.length(); right++){char in = ss[right];if(++hash2[in - 'a'] <= hash1[in - 'a']) count++;//进窗口与维护countif(right - left + 1 > p.length()){//判断char out = ss[left++];if(hash2[out - 'a']-- <= hash1[out - 'a']) count--;//出窗口与维护count}if(count == p.length()) ret.add(left);}return ret;}
}
1.3. 串联所有单词的子串

题目要求我们,将字符串数组的子字符串串联,然后在字符串s中的一个字串找出字母异位词。与上一题类似,但这道题面对的是一个一个的字符串,但我们依然可以利用滑动窗口和哈希表来解决。首先在哈希表上,这里需要用到容器来映射字符串和字符串出现的次数;在指针移动上,right指针不能一次移动一个字符,长度应与words里的字符串长度一致。对于滑动窗口的执行次数(如下图),我们只需要执行这3次滑动窗口的操作就可以找出,其他操作都是多余的。所以滑动窗口的执行次数也是字符串数组中字符的长度。

完整代码实现:
class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> ret = new ArrayList<>();Map<String,Integer> hash1 = new HashMap<String,Integer>();//保存words里面单词的频次for(String str : words) hash1.put(str, hash1.getOrDefault(str,0)+1);//把单词丢进哈希表里面,并单词个数int len = words[0].length(),m = words.length;for (int i = 0; i < len; i++) {//执行次数Map<String,Integer> hash2 = new HashMap<String,Integer>();//统计窗口内单词的频次for (int left = i,right = i,count = 0;right + len <= s.length();right += len){//count用来统计有效字符串的个数//进窗口与维护countString in = s.substring(right,right+len);hash2.put(in,hash2.getOrDefault(in,0)+1);if(hash2.get(in) <= hash1.getOrDefault(in,0)) count++;//判断if(right - left + 1 > len * m){//出窗口与维护countString out = s.substring(left,left+len);if(hash2.get(out) <= hash1.getOrDefault(out,0)) count--;hash2.put(out,hash2.get(out) - 1);left += len;}if(count == m) ret.add(left);}}return ret;}
}
1.4. 最小覆盖子串

我们先理清题目要求:题目要我们从字符串s中找到一个最小子串,与字符串t构成包含关系。如何没有这样的子串,返回空字符串“”。
我们还是先来思考一下暴力解法:先定义两个指针,我们以其中一个指针为起点,另一个指针向右移动,找到所有符合条件的子串,从里面挑出最短的长度。如果转化成代码,依然是借助哈希表, 将遍历过的字符丢进哈希表中进行统计直到里面的字符个数大于等于t中的即可。

接下来对暴力解法进行一个优化。我们看下图,我们从s中找出一段符合要求的子串,然后让left向后移动一步,此时会出现两种情况,要么缩小的区间还是符合要求,要么不符合要求,我们就让right向右移动,并且在这期间right是不需要回退的。这时候我们就可以用滑动窗口与双指针来解决。

进窗口,把s中的字符串丢进哈希表中统计。当窗口是合法的时候,判断两个哈希表里的字符个数,再让left向左移动。我们最后是要返回一个字符串,所以们需要知道起始位置和最终位置来决定我们什么时候出窗口。
如果我们只去遍历一遍哈希表,那么这个算法的时间复杂度是非常高的。我们还需要对算法进行优化。与前两题一样,在定义变量count。只不过这次的count是统计字符的种类,因为在找字母异位词时,子串和字符串是一一对应的关系,这里字符却是大于等于的关系。进窗口之后,比较hash1(in) == hash2(in)(这里之所以不是大于等于,是因为不会统计进重复的子串)。出之前,比较hash1(out) == hash2(out),就能保证出之后窗口不是有效的。因为统计的是字符的种类,所以count = hash1的长度。
{public String minWindow(String s,String t){char[] ss = s.toCharArray();char[] tt = t.toCharArray();int[] hash1 = new int[128];//统计字符串t中的频次int kinds = 0;//t中有多少种字符for(char ch : tt)if(hash1[ch]++ == 0) kinds++;int[] hash2 = new int[128];int minlen = Integer.MAX_VALUE, begin = -1;for(int left = 0,right = 0,count = 0;right < ss.length; right++){char in = ss[right];if(++hash2[in] == hash1[in]) count++;//进窗口与维护countwhile(kinds == count){//判断//更新结果if(right - left +1 < minlen){begin = left;minlen = right - left + 1;}char out = ss[left++];if(hash2[out]-- == hash1[out]) count--;//出窗口与维护count}}if(begin == -1) return new String();else return s.substring(begin,begin+minlen);}
}相关文章:
优选算法的智慧之光:滑动窗口专题(二)
专栏:算法的魔法世界 个人主页:手握风云 目录 一、例题讲解 1.1. 最大连续1的个数 III 1.2. 找到字符串中所有字母异位词 1.3. 串联所有单词的子串 1.4. 最小覆盖子串 一、例题讲解 1.1. 最大连续1的个数 III 题目要求是二进制数组&am…...
Kylin麒麟操作系统服务部署 | NFS服务部署
以下所使用的环境为: 虚拟化软件:VMware Workstation 17 Pro 麒麟系统版本:Kylin-Server-V10-SP3-2403-Release-20240426-x86_64 一、 NFS服务概述 NFS(Network File System),即网络文件系统。是一种使用于…...
7.1.2 计算机网络的分类
文章目录 分布范围交换方式 分布范围 计算机网络按照分布范围可分为局域网、广域网、城域网。局域网的范围在10m~1km,例如校园网,网速高,主要用于共享网络资源,拓扑结构简单,约束少。广域网的范围在100km,例…...
Spring Cloud Alibaba 实战:轻松实现 Nacos 服务发现与动态配置管理
1. Nacos 介绍 1.1 什么是 Nacos? Nacos(Naming and Configuration Service)是阿里巴巴开源的一个服务注册中心和配置管理中心。它支持动态服务发现、配置管理和服务治理,适用于微服务架构,尤其是基于 Spring Cloud …...
【数据结构】LRUCache|并查集
目录 一、LRUCache 1.概念 2.实现:哈希表双向链表 3.JDK中类似LRUCahe的数据结构LinkedHashMap 🔥4.OJ练习 二、并查集 1. 并查集原理 2.并查集代码实现 3.并查集OJ 一、LRUCache 1.概念 最近最少使用的,一直Cache替换算法 LRU是Least Recent…...
智能合约中权限管理不当
权限管理不当 : 权限管理不当是智能合约中常见的安全问题之一,尤其是在管理员或特定账户被过度赋予权限的情况下。如果合约中的关键功能,如转移资产、修改合约状态或升级合约逻辑,可以被未经授权的实体随意操作,这将构…...
MariaDB Galera 原理及用例说明
一、底层原理 MariaDB Galera 集群是一种基于同步多主架构的高可用数据库解决方案,适合需要高并发、低延迟和数据强一致性的场景。以下是部署和配置 MariaDB Galera 集群的简明步骤: 1. 环境准备 节点要求:至少 3 个节点(奇数节点…...
【RAG 篇】万字长文:向量数据库选型指南 —— Milvus 与 FAISS/Pinecone/Weaviate 等工具深度对比
大家好,我是大 F,深耕AI算法十余年,互联网大厂技术岗。分享AI算法干货、技术心得。 欢迎关注《大模型理论和实战》、《DeepSeek技术解析和实战》,一起探索技术的无限可能! 文章目录 向量数据库的核心价值主流工具横向对比 FAISS:Meta 的高效检索引擎Pinecone:全托管商业…...
关于服务器cpu过高的问题排查
1.定位是哪个程序造成的cpu过高 如果有云服务器,就用云服务器自带的监控功能,查时间段 如果没有,则使用: ps -eo pid,comm,pcpu,pmem,cputime --sort-cputime | head -n 100 2.定位到问题 发现是uwsgi的cpu消耗过高࿰…...
Gpt翻译完整版
上一篇文章收到了很多小伙伴的反馈,总结了一下主要以下几点: 1. 说不知道怎么调api 2. 目前只是把所有的中文变成了英文,如果想要做多语言还需要把这些关键字提炼出来成放到message_zh.properties和message_en.properties文件中,…...
雷池WAF的为什么选择基于Docker
Docker 是一种开源的容器化平台,可以帮助开发人员将应用程序及其所有依赖项打包到一个称为容器的独立、可移植的环境中。Docker 的核心概念包括以下几点: 容器:Docker 使用容器来封装应用程序及其依赖项,使其能够在任何环境中都能…...
美股回测:历史高频分钟数据的分享下载与策略解析20250305
美股回测:历史高频分钟数据的分享下载与策略解析20250305 在金融分析和投资决策的精细化过程中,美股历史分钟高频数据发挥着至关重要的作用。这些数据以其详尽性和精确性,记录了股票每分钟的价格波动和成交量变化,为投资者提供了…...
【文生图】windows 部署stable-diffusion-webui
windows 部署stable-diffusion-webui AUTOMATIC1111 stable-diffusion-webui Detailed feature showcase with images: 带图片的详细功能展示: Original txt2img and img2img modes 原始的 txt2img 和 img2img 模式 One click install and run script (but you still must i…...
[Python入门学习记录(小甲鱼)]第3章 Python基础知识
第3章 基础知识 前面三章都没啥用,这一章开始进入主题。 3.1 变量 变量顾名思义就是一个可变的量,但Python的变量更像是一个名字,通过这个名字可以找到我们想要的值。注意点如下: Python不需要显式声明,但使用之前…...
某系统webpack接口泄露引发的一系列漏洞
视频教程在我主页简介或专栏里 (不懂都可以来问我 专栏找我哦) 目录: 信息搜集 未授权敏感信息泄露越权任意用户密码重置 1.越权访问 2.大量敏感信息 越权 任意用户密码重置 信息搜集 这里找到从小穿一条裤子长大的兄弟,要挟他交…...
【计算机网络入门】初学计算机网络(十一)重要
目录 1. CIDR无分类编址 1.1 CIDR的子网划分 1.1.1 定长子网划分 1.1.2 变长子网划分 2. 路由聚合 2.1 最长前缀匹配原则 3. 网络地址转换NAT 3.1 端口号 3.2 IP地址不够用? 3.3 公网IP和内网IP 3.4 NAT作用 4. ARP协议 4.1 如何利用IP地址找到MAC地址…...
决策树(Decision Tree)基础知识
目录 一、回忆1、*机器学习的三要素:1)*函数族2)*目标函数2.1)*模型的其他复杂度参数 3)*优化算法 2、*前处理/后处理1)前处理:特征工程2)后处理:模型选择和模型评估 3、…...
Nat Mach Intell | AI分子对接算法评测
《Nature Machine Intelligence》发表重磅评测,系统评估AI与物理方法在虚拟筛选(VS)中的表现,突破药物发现效率瓶颈。 核心评测体系:三大数据集 研究团队构建了三个新型测试集: TrueDecoy:含14…...
【自学笔记】Hadoop基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Hadoop基础知识点总览1. Hadoop简介2. Hadoop生态系统3. HDFS(Hadoop Distributed File System)HDFS基本命令 4. MapReduceWordCount示例&am…...
【Linux】使用问题汇总
#1 ssh连接的时候报Key exchange failed 原因:服务端版本高,抛弃了一些不安全的交换密钥算法,且客户端版本比较旧,不支持安全性较高的密钥交换算法。 解决方案: 如果是内网应用,安全要求不这么高…...
卷积神经网络文本分类终极指南:3,4,5多尺寸滤波器配置详解
卷积神经网络文本分类终极指南:3,4,5多尺寸滤波器配置详解 【免费下载链接】cnn-text-classification-tf Convolutional Neural Network for Text Classification in Tensorflow 项目地址: https://gitcode.com/gh_mirrors/cn/cnn-text-classification-tf 在…...
run-aspnetcore-microservices 购物车微服务:Redis分布式缓存与Grpc同步通信实现
run-aspnetcore-microservices 购物车微服务:Redis分布式缓存与Grpc同步通信实现 【免费下载链接】run-aspnetcore-microservices aspnetrun/run-aspnetcore-microservices: 是一个用于部署和运行 ASP.NET Core 微服务应用程序的开源项目,提供了一个简单…...
可视化拖拽组件库终极指南:响应式设计与适配方案完整解析
可视化拖拽组件库终极指南:响应式设计与适配方案完整解析 【免费下载链接】visual-drag-demo 一个低代码(可视化拖拽)教学项目 项目地址: https://gitcode.com/gh_mirrors/vi/visual-drag-demo 可视化拖拽组件库是现代低代码开发平台的…...
从Netfilter到IPVS:深入解析Linux内核负载均衡的实现与配置
1. Linux内核网络框架与负载均衡基础 当你打开一个网页或使用手机APP时,后台可能有成百上千台服务器在协同工作。这些服务器如何高效分配流量?这就是负载均衡技术的用武之地。在Linux生态中,从Netfilter到IPVS的技术演进,为我们提…...
WPF Chart控件实战:构建高性能实时数据监控曲线
1. WPF Chart控件基础入门 第一次接触WPF Chart控件时,我也被它强大的功能震撼到了。这个控件就像是一个神奇的画板,能够将枯燥的数据变成直观的曲线图。在工业监控系统中,我们经常需要实时显示温度、压力等参数的变化趋势,这时候…...
大麦抢票神器:3分钟快速上手,轻松搞定热门演出门票
大麦抢票神器:3分钟快速上手,轻松搞定热门演出门票 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 你是一个文章写手&#x…...
OpenWrt固件下载与配置教程:R5S设备从入门到精通
OpenWrt固件下载与配置教程:R5S设备从入门到精通 【免费下载链接】openwrt openwrt编译更新库X86-R2C-R2S-R4S-R5S-N1-小米MI系列等多机型全部适配OTA自动升级 项目地址: https://gitcode.com/GitHub_Trending/openwrt5/openwrt GitHub_Trending/openwrt5/op…...
告别手动启动:教你写一个ROS2 Launch文件,一键运行robot_state_publisher和rviz2显示URDF
ROS2高效开发指南:用Launch文件一键启动机器人可视化系统 每次调试URDF模型都要重复输入一堆命令?手动启动robot_state_publisher、joint_state_publisher和rviz2节点不仅浪费时间,还容易遗漏参数。本文将带你深度掌握ROS2 Launch文件的编写…...
告别COLMAP预处理:3D高斯溅射的零配置新体验
告别COLMAP预处理:3D高斯溅射的零配置新体验 【免费下载链接】CF-3DGS 项目地址: https://gitcode.com/gh_mirrors/cf/CF-3DGS 想象一下,你刚刚拍摄了一组精美的场景照片,想要快速生成3D模型,却发现需要先运行复杂的COLMA…...
别再只盯着运放了:用跨阻放大器搞定光电传感器信号调理的完整指南
光电传感器信号调理实战:跨阻放大器设计与避坑指南 当你在昏暗的灯光下测试光电传感器时,是否曾被微弱的电流信号折磨得焦头烂额?作为嵌入式工程师,我曾在凌晨三点的实验室里,面对闪烁不定的示波器波形,才…...
