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



专栏:算法的魔法世界
个人主页:手握风云
目录
一、例题讲解
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 原因:服务端版本高,抛弃了一些不安全的交换密钥算法,且客户端版本比较旧,不支持安全性较高的密钥交换算法。 解决方案: 如果是内网应用,安全要求不这么高…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
