当前位置: 首页 > news >正文

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

 专栏:算法的魔法世界​​​​​​

个人主页:手握风云

目录

一、例题讲解

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→O(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);}
}

相关文章:

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

专栏&#xff1a;算法的魔法世界​​​​​​ 个人主页&#xff1a;手握风云 目录 一、例题讲解 1.1. 最大连续1的个数 III 1.2. 找到字符串中所有字母异位词 1.3. 串联所有单词的子串 1.4. 最小覆盖子串 一、例题讲解 1.1. 最大连续1的个数 III 题目要求是二进制数组&am…...

Kylin麒麟操作系统服务部署 | NFS服务部署

以下所使用的环境为&#xff1a; 虚拟化软件&#xff1a;VMware Workstation 17 Pro 麒麟系统版本&#xff1a;Kylin-Server-V10-SP3-2403-Release-20240426-x86_64 一、 NFS服务概述 NFS&#xff08;Network File System&#xff09;&#xff0c;即网络文件系统。是一种使用于…...

7.1.2 计算机网络的分类

文章目录 分布范围交换方式 分布范围 计算机网络按照分布范围可分为局域网、广域网、城域网。局域网的范围在10m~1km&#xff0c;例如校园网&#xff0c;网速高&#xff0c;主要用于共享网络资源&#xff0c;拓扑结构简单&#xff0c;约束少。广域网的范围在100km&#xff0c;例…...

Spring Cloud Alibaba 实战:轻松实现 Nacos 服务发现与动态配置管理

1. Nacos 介绍 1.1 什么是 Nacos&#xff1f; Nacos&#xff08;Naming and Configuration Service&#xff09;是阿里巴巴开源的一个服务注册中心和配置管理中心。它支持动态服务发现、配置管理和服务治理&#xff0c;适用于微服务架构&#xff0c;尤其是基于 Spring Cloud …...

【数据结构】LRUCache|并查集

目录 一、LRUCache 1.概念 2.实现:哈希表双向链表 3.JDK中类似LRUCahe的数据结构LinkedHashMap &#x1f525;4.OJ练习 二、并查集 1. 并查集原理 2.并查集代码实现 3.并查集OJ 一、LRUCache 1.概念 最近最少使用的&#xff0c;一直Cache替换算法 LRU是Least Recent…...

智能合约中权限管理不当

权限管理不当 &#xff1a; 权限管理不当是智能合约中常见的安全问题之一&#xff0c;尤其是在管理员或特定账户被过度赋予权限的情况下。如果合约中的关键功能&#xff0c;如转移资产、修改合约状态或升级合约逻辑&#xff0c;可以被未经授权的实体随意操作&#xff0c;这将构…...

MariaDB Galera 原理及用例说明

一、底层原理 MariaDB Galera 集群是一种基于同步多主架构的高可用数据库解决方案&#xff0c;适合需要高并发、低延迟和数据强一致性的场景。以下是部署和配置 MariaDB Galera 集群的简明步骤&#xff1a; 1. 环境准备 节点要求&#xff1a;至少 3 个节点&#xff08;奇数节点…...

【RAG 篇】万字长文:向量数据库选型指南 —— Milvus 与 FAISS/Pinecone/Weaviate 等工具深度对比

大家好,我是大 F,深耕AI算法十余年,互联网大厂技术岗。分享AI算法干货、技术心得。 欢迎关注《大模型理论和实战》、《DeepSeek技术解析和实战》,一起探索技术的无限可能! 文章目录 向量数据库的核心价值主流工具横向对比 FAISS:Meta 的高效检索引擎Pinecone:全托管商业…...

关于服务器cpu过高的问题排查

1.定位是哪个程序造成的cpu过高 如果有云服务器&#xff0c;就用云服务器自带的监控功能&#xff0c;查时间段 如果没有&#xff0c;则使用&#xff1a; ps -eo pid,comm,pcpu,pmem,cputime --sort-cputime | head -n 100 2.定位到问题 发现是uwsgi的cpu消耗过高&#xff0…...

Gpt翻译完整版

上一篇文章收到了很多小伙伴的反馈&#xff0c;总结了一下主要以下几点&#xff1a; 1. 说不知道怎么调api 2. 目前只是把所有的中文变成了英文&#xff0c;如果想要做多语言还需要把这些关键字提炼出来成放到message_zh.properties和message_en.properties文件中&#xff0c…...

雷池WAF的为什么选择基于Docker

Docker 是一种开源的容器化平台&#xff0c;可以帮助开发人员将应用程序及其所有依赖项打包到一个称为容器的独立、可移植的环境中。Docker 的核心概念包括以下几点&#xff1a; 容器&#xff1a;Docker 使用容器来封装应用程序及其依赖项&#xff0c;使其能够在任何环境中都能…...

美股回测:历史高频分钟数据的分享下载与策略解析20250305

美股回测&#xff1a;历史高频分钟数据的分享下载与策略解析20250305 在金融分析和投资决策的精细化过程中&#xff0c;美股历史分钟高频数据发挥着至关重要的作用。这些数据以其详尽性和精确性&#xff0c;记录了股票每分钟的价格波动和成交量变化&#xff0c;为投资者提供了…...

【文生图】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章 基础知识 前面三章都没啥用&#xff0c;这一章开始进入主题。 3.1 变量 变量顾名思义就是一个可变的量&#xff0c;但Python的变量更像是一个名字&#xff0c;通过这个名字可以找到我们想要的值。注意点如下&#xff1a; Python不需要显式声明&#xff0c;但使用之前…...

某系统webpack接口泄露引发的一系列漏洞

视频教程在我主页简介或专栏里 &#xff08;不懂都可以来问我 专栏找我哦&#xff09; 目录&#xff1a; 信息搜集 未授权敏感信息泄露越权任意用户密码重置 1.越权访问 2.大量敏感信息 越权 任意用户密码重置 信息搜集 这里找到从小穿一条裤子长大的兄弟&#xff0c;要挟他交…...

【计算机网络入门】初学计算机网络(十一)重要

目录 1. CIDR无分类编址 1.1 CIDR的子网划分 1.1.1 定长子网划分 1.1.2 变长子网划分 2. 路由聚合 2.1 最长前缀匹配原则 3. 网络地址转换NAT 3.1 端口号 3.2 IP地址不够用&#xff1f; 3.3 公网IP和内网IP 3.4 NAT作用 4. ARP协议 4.1 如何利用IP地址找到MAC地址…...

决策树(Decision Tree)基础知识

目录 一、回忆1、*机器学习的三要素&#xff1a;1&#xff09;*函数族2&#xff09;*目标函数2.1&#xff09;*模型的其他复杂度参数 3&#xff09;*优化算法 2、*前处理/后处理1&#xff09;前处理&#xff1a;特征工程2&#xff09;后处理&#xff1a;模型选择和模型评估 3、…...

Nat Mach Intell | AI分子对接算法评测

《Nature Machine Intelligence》发表重磅评测&#xff0c;系统评估AI与物理方法在虚拟筛选&#xff08;VS&#xff09;中的表现&#xff0c;突破药物发现效率瓶颈。 核心评测体系&#xff1a;三大数据集 研究团队构建了三个新型测试集&#xff1a; TrueDecoy&#xff1a;含14…...

【自学笔记】Hadoop基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Hadoop基础知识点总览1. Hadoop简介2. Hadoop生态系统3. HDFS&#xff08;Hadoop Distributed File System&#xff09;HDFS基本命令 4. MapReduceWordCount示例&am…...

【Linux】使用问题汇总

#1 ssh连接的时候报Key exchange failed 原因&#xff1a;服务端版本高&#xff0c;抛弃了一些不安全的交换密钥算法&#xff0c;且客户端版本比较旧&#xff0c;不支持安全性较高的密钥交换算法。 解决方案&#xff1a; 如果是内网应用&#xff0c;安全要求不这么高&#xf…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...