Java之滑动窗口详解

news2024/9/23 9:33:05

目录

一.滑动窗口

1.什么滑动窗口

2.滑动窗口的三要素

二.找到字符串中所有字母异位词

1.题目描述

2.问题分析 

3.代码实现

三.字符串的排列

1.题目描述

2.问题分析

3.代码实现

四.考试的最大困扰度

1.题目描述

2.问题分析

3.代码实现

五.替换后的最长重复字符

1.题目描述

2.问题分析

3.代码实现

六.尽可能使字符串相等

1.题目描述

2.问题分析

3.代码实现

七.每种字符至少取 K 个

1.题目描述

2.问题分析

3.代码实现


一.滑动窗口

1.什么滑动窗口

滑动窗口是通过双指针同向移动而解决的一类问题

经常用于数组或者字符串,求其满足条件的连续子序列或者子串,将原先需要嵌套循环问题,转换为单循环问题,降低时间复杂度

主要分为两大类,一种是长度固定的滑动窗口,一种是长度动态变化的滑动窗口

2.滑动窗口的三要素

我们分析问题主要就是考虑这三要素,寻找满足题意的条件,使窗口的右端(right)可以向右滑行,满足条件的时候,使窗口的左端(left)向右滑行,进行收缩,直到对整个数组(或字符串)线性遍历完成

窗口扩展是寻找可行解

窗口收缩是优化可行解

窗口只能从左至右滑动

注意:长度固定的滑动窗口不需要扩张和收缩,只需要保持固定的长度向右滑动即可

二.找到字符串中所有字母异位词

1.题目描述

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

力扣:力扣

2.问题分析 

首先我们需要理解异位词,其实就是含有各个字母数量和一个子串的字母数量相同,那么就可以成为异位,例如(aab)和(baa),他们的长度也是相同的,所以只需要在字符串s中找到长度和p字符串长度相同且各个字母数量相同的字符串即可.这很容易可以想象到滑动窗口,并且长度固定为p的长度的窗口

这里我们采用一个长度为26的字符数组来统计长度为p长度的滑动窗口的字母数量,和p的字符数组进行比较,相同即可加入到list数组中

3.代码实现

    public List<Integer> findAnagrams(String s, String p) {
       ArrayList<Integer> list = new ArrayList<>();
        if (p.length() > s.length())
            return list;
        int[] sCount = new int[26];
        int[] pCount = new int[26];
        for (int i = 0; i < p.length(); ++i) {
            pCount[p.charAt(i) - 'a']++;
        }
        for (int i = 0; i < p.length() - 1; ++i) {
            sCount[s.charAt(i)-'a']++;
        }

        for (int i = 0; i <= s.length() - p.length(); ++i) {
            sCount[s.charAt(i + p.length() - 1)-'a']++;
            if (Arrays.equals(sCount, pCount)) {
                list.add(i);
            }
            sCount[s.charAt(i)-'a']--;
        }
        return list;

    }

三.字符串的排列

1.题目描述

给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false

换句话说,s1 的排列之一是 s2子串

力扣: 力扣

2.问题分析

这一题和上一题大致相似,自己可以来尝试一下,排列其实就是异位

3.代码实现

    public boolean checkInclusion(String s1, String s2) {
        if(s1.length()>s2.length())
        return false;
        char[] countS1 = new char[26];
        char[] countS2 = new char[26];

        for (int i = 0; i < s1.length(); ++i) {
            countS1[s1.charAt(i) - 'a']++;
            countS2[s2.charAt(i) - 'a']++;
        }
        if (Arrays.equals(countS1, countS2)) {
            return true;
        }
        for (int i = s1.length(); i < s2.length(); ++i) {
            countS2[s2.charAt(i - s1.length()) - 'a']--;
            countS2[s2.charAt(i) - 'a']++;
            if (Arrays.equals(countS1, countS2)) {
                return true;
            }
        }
        return false;

    }

四.考试的最大困扰度

1.题目描述

一位老师正在出一场由 n 道判断题构成的考试,每道题的答案为 true (用 'T' 表示)或者 false (用 'F' 表示)。老师想增加学生对自己做出答案的不确定性,方法是 最大化 连续相同 结果的题数。(也就是连续出现 true 或者连续出现 false)。

给你一个字符串 answerKey ,其中 answerKey[i] 是第 i 个问题的正确结果。除此以外,还给你一个整数 k ,表示你能进行以下操作的最多次数:

  • 每次操作中,将问题的正确答案改为 'T' 或者 'F' (也就是将 answerKey[i] 改为 'T' 或者 'F' )。

请你返回在不超过 k 次操作的情况下,最大 连续 'T' 或者 'F' 的数目。

力扣:力扣

2.问题分析

分析了问题可以知道,这一题包含了字符串,连续T或F字符最大的字眼,因此很容易想到需要使用滑动窗口,因为不确定最大连续字符串的长度,所以这一题的窗口长度是不固定的.问题其实可以分为以下两种情况:

第一种情况:使用k次机会将遇到的F变成T,在这种情况下使求得连续T的最大数目.

第二种情况:使用k次机会将遇到的T变成F,在这种情况下使求得连续F的最大数目.

最后只需要求得T和F连续的最大数目两者的最大值即可

分析窗口扩张的情况:(拿求连续T长度最大)因为有k次机会,所以当窗口中F数量小于等于k的时候,这个时候窗口的right向右滑行

分析窗口收缩的情况:当窗口中F的数量大于k的时候,这个时候窗口left进行收缩,直到k的数量小于等于k的时候

满足条件的窗口大小即为一个符合条件的连续T的长度,只需要寻找满足条件的窗口的最大值即可.

3.代码实现

    public int maxConsecutiveAnswers(String answerKey, int k) {
        return Math.max(maxCount(answerKey, k, 'T'), maxCount(answerKey, k, 'F'));
    }

    public int maxCount(String answerKey, int k, char c) {
        int ans = 0;
        for (int left = 0, right = 0, sum = 0; right < answerKey.length(); ++right) {
            sum += answerKey.charAt(right) != c ? 1 : 0;
            while (sum > k) {
                sum -= answerKey.charAt(left) != c ? 1 : 0;
                left++;
            }
            ans = Math.max(ans, right - left + 1);

        }
        return ans;

    }

五.替换后的最长重复字符

1.题目描述

给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。

在执行上述操作后,返回包含相同字母的最长子字符串的长度。

力扣:力扣

2.问题分析

这一题和上一题基本类似,上一题只包含T和F两种字符,这一题一共26中字符(A--Z),所以要比较26次最大值,求出结果.

分析窗口扩张的情况:当窗口中不等于c字符的数量小于等于k次的时候,窗口右端right向右滑行

分析窗口收缩的情况:当窗口中不等于c字符的数量大于k次的时候,窗口左端left向右滑行,直到窗口中c字符的数量小于等于k次.

3.代码实现

    public int characterReplacement(String s, int k) {
        int res = 0;
        HashSet<Character> set = new HashSet<>();
        for (char c : s.toCharArray()) {
            set.add(c);
        }
        for (Character character : set) {
            res = Math.max(res, countMax(s, k, character));
        }
        return res;

    }

    public int countMax(String s, int k, char c) {
        int res = 0;
        for (int left = 0, right = 0, cnt = 0; right < s.length(); ++right) {
            cnt += s.charAt(right) != c ? 1 : 0;
            while (cnt > k) {
                cnt -= s.charAt(left) != c ? 1 : 0;
                left++;
            }
            res = Math.max(res, right - left + 1);
        }
        return res;

    }

做完这题可以自己去做下:1004. 最大连续1的个数 III: 力扣   1493. 删掉一个元素以后全为 1 的最长子数组:力扣  

六.尽可能使字符串相等

1.题目描述

给你两个长度相同的字符串,st

s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。

用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。

如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。

如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0

力扣: 力扣

2.问题分析

这一题虽然和上一题不一样,但这一题更加简单,因为很容易想到窗口扩张和收缩的条件

分析窗口扩张的情况:当遍历到i位置的时候,所需要的预算小于等于maxCost的时候,窗口的右端可以继续向右滑行

分析窗口收缩的情况:当遍历到i位置的时候,所需要的预算大于maxCost的时候,窗口的右端不可以继续向右滑行,这个时候窗口左端left收缩,直到小于maxCost

3.代码实现

    public int equalSubstring(String s, String t, int maxCost) {
        int res = 0;
        for (int left = 0, right = 0, sum = 0; right < s.length(); ++right) {
            sum += Math.abs(t.charAt(right) - s.charAt(right));
            while (sum > maxCost) {
                sum -= Math.abs(t.charAt(left) - s.charAt(left));
                left++;
            }
            res = Math.max(res, right - left + 1);

        }
        return res;

    }

七.每种字符至少取 K 个

1.题目描述

给你一个由字符 'a''b''c' 组成的字符串 s 和一个非负整数 k 。每分钟,你可以选择取走 s 最左侧 还是 最右侧 的那个字符。

你必须取走每种字符 至少 k 个,返回需要的 最少 分钟数;如果无法取到,则返回 -1

力扣:力扣

2.问题分析

正难则反,我们不妨换一个角度考虑一下问题,问题是我们每次从左端或右端取走字符,最终使取走各k个字符'a','b','c',那么我们不妨这样考虑:取走k个字符'a','b','c',字符串中还剩下多少个字符'a','b','c',求出长度最大的含有这样的子串,最终最小的分钟等于字符串的长度减去这个子串

设子串中要剩余至多cntA个'a',cntB个'b',cntC个'c'

分析窗口扩张的情况:当子串(滑动窗口)中所有字母的数量小于等于所需的数量(cntA,cntB,cntC)时候,窗口的right端向右滑行

分析窗口收缩的情况:当子串(滑动窗口)中任一个字母的数量大于所需的数量(cntA,cntB,cntC)时候,窗口的left端向左滑行,直至不符合条件

每次需要收集满足条件的窗口的长度,寻找到最大长度的窗口,最终的答案就是字符串的长度减去滑动窗口长度的最大值

3.代码实现

    public int takeCharacters(String s, int k) {
        int left = 0, right = 0, length = s.length();
        char[] arr = s.toCharArray();
        int max = 0;
        int[] cnt = new int[3];//统计a,b,c的数量
        for (int i = 0; i < length; ++i) {
            cnt[arr[i] - 'a']++;
        }
        int cntA = cnt[0] - k, cntB = cnt[1] - k, cntC = cnt[2] - k;//分别为a,b,c可以剩下的最大数量
        if (cntA == 0 && cntB == 0 && cntC == 0)//此时要全部取走
            return length;
        if (cntA < 0 || cntB < 0 || cntC < 0)//剩下的数量为负的时候,说明a,b,c的数量不足k个
            return -1;
        cnt = new int[3];//每次循环统计剩下的a,b,c的数量
        while (right < length) {
            cnt[arr[right] - 'a']++;
            while (cnt[0] > cntA || cnt[1] > cntB || cnt[2] > cntC) {
                cnt[arr[left] - 'a']--;
                left++;//当剩下的字符串过长而不满足条件的时候,滑动窗口左端向右移
            }
            max = Math.max(max, right - left+1);
            right++;//窗口的左端向右移


        }

        return length - max;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351418.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git命令行推送本地分支到远程仓库

之前说过Git与IDEA强强联合&#xff08;HTTPS协议连接&#xff09;那么如何使用命令行来推送代码呢&#xff1f; 如下图所示为一个基于layui的前端代码&#xff1a; 目录工作区文件&#xff1a; 本地内容就是将这些内容推送到远程仓库 首先使用git命令初始化git本地仓库&…

阿里巴巴测试岗,3面都过了,到头来却因为这个原因被刷了...

说在前面 面试时最好不要虚报工资。本来阿里巴巴是很想去的&#xff0c;几轮面试也通过了&#xff0c;最后没offer&#xff0c;自己只想到下面几个原因 虚报工资&#xff0c;比实际高30%&#xff1b;有更好的人选&#xff0c;这个可能性不大&#xff0c;我看还在招聘。我是面…

【Redis】Redis持久化之AOF详解(Redis专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建工设优化。文章内容兼具广度深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于知名金融公…

Windows11安装OpenSSH客户端,实现ssh远程连接云服务器

一、打开设置 - 应用 - 添加可选功能&#xff0c;选择安装OpenSSH客户端 二、安装完之后&#xff0c;验证 ssh 命令 1、启动ssh服务之后&#xff0c;打开 cmd 窗口已支持连接 三、如果 ssh 命令仍然不生效&#xff0c;需要配置 ssh 环境变量 1、新建 SSH_HOME 环境变量&#…

2023 年前端十大 Web 发展趋势

很长一段时间&#xff0c;Web 开发的前景似乎没有什么进展&#xff08;2016 年至 2021 年&#xff09;&#xff0c;但在刚刚过去的 2022 年中确实又猛窜了一波。今天主要想跟大家聊聊最新 Web 开发趋势。相信这波浪潮会继续激发 Web 开发者的关注&#xff0c;对万象更新的 2023…

视频连载11 - 这个为生信学习和生信作图打造的开源R教程真香!!!

点击阅读原文跳转完整教案。1 思考题2 R基础2.1 R安装2.2 Rstudio基础2.2.1 Rstudio版本2.2.2 Rstudio安装2.2.3 Rstudio 使用2.3 R基本语法2.3.1 获取帮助文档&#xff0c;查看命令或函数的使用方法、事例或适用范围2.3.2 R中的变量及其初始化2.3.3 变量类型和转换2.3.4 R中矩…

MYSQL安装部署--Linux 仓库安装

声明 &#xff1a;# 此次我们安装的 MYSQL 版本是 8.0.32 版本 我们本次安装 MYSQL 总共要介绍 四种方式 # 仓库安装# 本地安装# 容器安装# 源码安装我们本篇介绍的是 仓库安装 仓库安装 下载 MYSQL 安装包 # MYSQL 安装&#xff0c;我们都是基于 MYSQL 官方网站里进行下载~&a…

计数系统架构设计(转)

本文主要节选和总结自沈剑大佬的 计数系统架构实践一次搞定 | 架构师之路和文章的评论&#xff0c;略有删改 一、问题描述 很多业务都有“计数”需求&#xff0c;以微博为例&#xff1a; 微博首页的个人中心部分&#xff0c;有三个重要的计数&#xff1a;关注了多少人的计数、粉…

如何编写一个基本的 Verilog Module(模块)

1、概述这篇文章主要介绍了 Verilog 在 FPGA 设计中的概念和使用方法。首先讨论使用模块&#xff08;module&#xff09;关键字构造 Verilog 设计的方式&#xff0c;以及这与所描述的硬件的关系。这包括对参数、端口&#xff08;port&#xff09;和例化&#xff08;instantiato…

JSON Web Token (JWT)

1&#xff0c;什么是JWT JWT是JSON Web Token是简称&#xff0c;是一个行业开发标准&#xff08;RFC 7519&#xff09;定义了一种简介的 自包含的协议格式&#xff0c;用于在通信双方传递JSON对象&#xff0c;传递的信息经过数字签名可以被验证和信任。它可以使用HMAC算法或使…

4.如何靠IT逆袭大学?

学习的动力不止于此&#xff1a; IT逆袭 这两天利用工作空余时间读了贺利坚老师的《逆袭大学——传给 IT 学子的正能量》&#xff0c;感触很多&#xff0c;有些后悔没有好好利用大学时光。 不过人都是撞了南墙再回头的&#xff0c;吃一堑长一智。 这本书无论你是工作了还是…

DataX简介、部署、原理和使用介绍

DataX简介、部署、原理和使用介绍 1.DataX简介 1-1.项目地址 项目地址&#xff1a;https://github.com/alibaba/DataX 官方文档&#xff1a;https://github.com/alibaba/DataX/blob/master/introduction.md 1-2.DataX概述 ​ DataX 是阿里云 DataWorks数据集成 的开源版本…

JDK安装环境变量配置

jdk下载地址:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html 下载安装包和exe都可。 安装JDK 安装JDK时&#xff0c;除了修改安装目录&#xff0c;其他的一路【下一步】&#xff0c;傻瓜式安装。 &#xff08;注&#xff1a;当提示安装JRE时…

WPF MVVM系统入门-上

WPF MVVM系统入门-上 Models:存放数据的模型&#xff0c;实体对象 Views:可视化界面 ViewModels:业务逻辑。ViewModels与Models的联系会更紧密&#xff0c;而Views页面会主动绑定ViewModels中的数据&#xff0c;原则上ViewModels不要直接去操作Views&#xff0c;被动的被Vie…

教唆chat ai 吵架--chatGPT和chatBing体验

教唆chat ai 吵架–chatGPT和chatBing体验 请注意&#xff0c;本文主观性非常高&#xff0c;只是一个参考性文章&#xff0c;无任何其他含义。 当我们谈到人工智能对话模型时&#xff0c;ChatGPT和ChatBing是两个备受关注的模型。它们都是自然语言处理领域中的重要里程碑&…

hive学习(仅供参考)

hive搭建Hive什么是hiveHive的优势和特点hive搭建解压、改名修改环境变量添加hive-site.xml将maven架包拷贝到hive替换一下gua包使环境变量生效初始化安装成功Hive 什么是hive 将结构化的数据文件映射为数据库表 提供类sql的查询语言HQL(Hive Query Language) Hive让更多的人…

【C++内存管理机制】学习笔记(4):重载operate new/::operator new..../new()

目录 简介C++应用程序 分配内存的途径重载::operator new/::operator delete重载operator new/operator delete重载new()/delete()结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简…

自学软件测试?一般人“别来沾边”...

本人7年测试经验&#xff0c;在学测试之前对电脑的认知也就只限于上个网&#xff0c;玩个办公软件。这里不能跑题&#xff0c;我为啥说&#xff1a;自学软件测试&#xff0c;一般人我还是劝你算了吧&#xff1f;因为我就是那个一般人&#xff01; 软件测试基础真的很简单&…

mac环境,安装NMP遇到的问题

一 背景 项目开发中,公司项目需要使用本地的环境运行,主要是php这块的业务。没有使用docker来处理,重新手动撸了一遍。记录下其中遇到的问题; 二 遇到的问题 2.1 Nginx的问题 brew install nginx后,启动nginx,报错如下:nginx: [emerg] no "ssl_certificate" …

数据结构与算法(二):线性表

上一篇《数据结构与算法&#xff08;一&#xff09;&#xff1a;概述》中介绍了数据结构的一些基本概念&#xff0c;并分别举例说明了算法的时间复杂度和空间复杂度的求解方法。这一篇主要介绍线性表。 一、基本概念 线性表是具有零个或多个数据元素的有限序列。线性表中数据…