滑动窗口在算法中的应用

news2024/12/23 10:58:10

滑动窗口是一种经典的算法技巧,就像在处理一系列动态数据时,用一扇可以滑动的“窗口”来捕捉一段连续的子数组或子字符串。通过不断地移动窗口的起点或终点,我们能够以较低的时间复杂度来解决一系列问题。在这篇文章中,我们将通过几个经典的 LeetCode 题目,使用 Java 语言来详细讲解滑动窗口的应用。


在这里插入图片描述

例题1:找到字符串中的所有异位词

题目背景
朋友小明在编程比赛中遇到了一个问题:如何在一个长字符串中找到所有与目标字符串异位的子串?我们需要通过滑动窗口找到所有这些位置。

题目描述
给定两个字符串 sp,找出 s 中所有 p 的异位词的起始索引。字符串仅包含小写字母,并且 ps 的长度都不超过 20,000。

示例

输入: s = "cbaebabacd", p = "abc"
输出: [0, 6]

代码实现

import java.util.*;

public class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> result = new ArrayList<>();
        if (s.length() < p.length()) return result;

        int[] pCount = new int[26];  // 记录字符串 p 中字符的频率
        int[] sCount = new int[26];  // 记录当前窗口中字符的频率

        for (char c : p.toCharArray()) {
            pCount[c - 'a']++;
        }

        int left = 0;
        for (int right = 0; right < s.length(); right++) {
            sCount[s.charAt(right) - 'a']++;
            
            // 如果窗口大小大于 p 的长度,收缩窗口
            if (right - left + 1 > p.length()) {
                sCount[s.charAt(left) - 'a']--;
                left++;
            }

            // 判断窗口内的字符频率与 p 是否一致
            if (Arrays.equals(sCount, pCount)) {
                result.add(left);
            }
        }
        
        return result;
    }
}

分析

  • 我们维护了两个频率表 pCountsCount,分别用于记录字符串 p 的字符频率和当前窗口的字符频率。
  • 时间复杂度为 O(n),其中 n 是字符串 s 的长度。

例题2:水果成篮

题目背景
我们去果园摘水果,朋友们想知道,如何在一个果树排列中,找到最长的连续子集,使得我们可以只用两个篮子装下这些水果。

题目描述
在一排树中,第 i 棵树上有 tree[i] 型号的水果。你可以选择两个篮子,每个篮子只能装一种型号的水果。你需要找到可以采摘的水果的最大数量。

示例

输入: tree = [1,2,1,2,1,3,3,4,3]
输出: 4

代码实现

import java.util.*;

public class Solution {
    public int totalFruit(int[] tree) {
        Map<Integer, Integer> basket = new HashMap<>();
        int left = 0, maxFruit = 0;

        for (int right = 0; right < tree.length; right++) {
            basket.put(tree[right], basket.getOrDefault(tree[right], 0) + 1);

            // 如果篮子里有超过两种水果,开始收缩窗口
            while (basket.size() > 2) {
                basket.put(tree[left], basket.get(tree[left]) - 1);
                if (basket.get(tree[left]) == 0) {
                    basket.remove(tree[left]);
                }
                left++;
            }

            // 记录当前窗口的最大长度
            maxFruit = Math.max(maxFruit, right - left + 1);
        }

        return maxFruit;
    }
}

分析

  • 这里我们使用 HashMap 来记录当前窗口中的水果种类和数量。
  • 当种类超过两个时,开始通过移动左指针缩小窗口,直到只剩下两种水果。
  • 时间复杂度为 O(n),空间复杂度为 O(1)。

例题3:最长重复字符替换

题目背景
小丽正在玩一个文字游戏,要求她通过最多 k 次字符替换,将字符串中的一段字符变成相同的字符。她希望找出其中能够获得最长重复字符子串的长度。

题目描述
给你一个仅由大写英文字母组成的字符串 s,你可以最多将 k 个字符替换为任意字符,求在执行上述操作后,能够得到的最长重复字符的子串的长度。

示例

输入: s = "AABABBA", k = 1
输出: 4

代码实现

public class Solution {
    public int characterReplacement(String s, int k) {
        int[] count = new int[26];  // 记录窗口内字符的频率
        int maxCount = 0, maxLen = 0, left = 0;

        for (int right = 0; right < s.length(); right++) {
            count[s.charAt(right) - 'A']++;
            maxCount = Math.max(maxCount, count[s.charAt(right) - 'A']);

            // 如果当前窗口大小减去窗口中最多的字符数大于 k,收缩窗口
            if (right - left + 1 - maxCount > k) {
                count[s.charAt(left) - 'A']--;
                left++;
            }

            maxLen = Math.max(maxLen, right - left + 1);
        }

        return maxLen;
    }
}

分析

  • 通过 count 数组记录每个字符的出现频率,并通过 maxCount 来维护窗口中出现最多的字符数。
  • 如果窗口的大小超过 k + maxCount,说明需要缩小窗口。
  • 时间复杂度为 O(n),因为我们只对每个字符遍历一次。

总结

滑动窗口在处理连续子数组或子字符串问题时展现了极大的灵活性。通过维护一个动态窗口,滑动窗口不仅能够帮助我们有效解决问题,还可以极大地优化时间复杂度。在这些例子中,我们用 Java 语言展示了滑动窗口在寻找异位词、最大水果采摘量、以及字符替换中的应用。滑动窗口算法的威力在于,它不仅高效,而且能够适应各种复杂的题目。

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

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

相关文章

图形视频处理软件Adobe After Effects(AE)2024WIN/MAC下载及系统要求

目录 一、Adobe AE软件简介 1.1 什么是Adobe AE软件 1.2 AE软件的发展历程 1.3 AE软件的应用领域 二、Adobe AE软件下载 2.1 下载 2.2 下载注意事项 三、Adobe AE软件系统要求 3.1 最低配置要求 3.2 推荐配置要求 3.3 显示器和分辨率 四、Adobe AE软件安装与使用 …

【MacOS】mac定位服务中删除已经卸载的软件

mac定位服务中删除已经卸载的软件 网上的帖子真不靠谱 直接右键 WeTypeSettings &#xff0c;查找位置&#xff0c;丢废纸篓即可&#xff01;会提示你卸载的&#xff01;

Pyramid: Real-Time LoRa Collision Decoding with Peak Tracking技术思考与解读

一点点个人的论文解读、技术理解&#xff0c;难免会有错误&#xff0c;欢迎大家一起交流和学习~~ &#x1f600;作者关于lora的系列文章从问题陈述到方法论的提出&#xff0c;再到实验评估&#xff0c;文章结构条理清晰&#xff0c;逻辑性强&#xff0c;并深入分析了LoRa信号处…

力扣刷题(5)

整数转罗马数字 整数转罗马数字-力扣 思路&#xff1a; 把各十百千位可能出现的情况都列出来&#xff0c;写成一个二维数组找出该数的各十百千位&#xff0c;与数组中的罗马元素对应 const char* ch[4][10]{{"", "I", "II", "III"…

webpack - 五大核心概念和基本配置(打包一个简单HTML页面)

// 五大核心概念 1. entry&#xff08;入口&#xff09; 指示Webpack从哪个文件开始打包2. output&#xff08;输出&#xff09; 指示Webpack打包完的文件输出到哪里去&#xff0c;如何命名等3. loader&#xff08;加载器&#xff09; webpack本身只能处理js&#xff0c;json等…

Bev pool 加速(2):自定义c++扩展

文章目录 1. c++扩展2. 案例2.1 案例12. 1.1 代码实现(1) c++ 文件(2) setup.py编写(3) python 代码编写2.1 案例1在bevfusion论文中,将bev_pooling定义为view transform中的效率瓶颈,bevfusion 主要就是对bev_pooling进行了加速,使得视图转换的速度提高了40倍,延迟从500ms…

charles配置安卓抓包(避坑版)

下载Charleshttps://www.charlesproxy.com/安装&#xff0c;疯狂点击下一步即可注册&#xff1a;打开Charles&#xff0c;选择“Help”菜单中的“Register Charles”&#xff0c;进网站生成密钥&#xff1a;https://www.zzzmode.com/mytools/charles/,将生成的密钥填入注册重启…

JavaScript练手小技巧:利用鼠标滚轮控制图片轮播

近日&#xff0c;在浏览网站的时候&#xff0c;发现了一个有意思的效果&#xff1a;一个图片轮播&#xff0c;通过上下滚动鼠标滚轮控制图片的上下切换。 于是就有了自己做一个的想法&#xff0c;顺带复习下鼠标滚轮事件。 鼠标滚轮事件&#xff0c;参考这篇文章&#xff1a;…

Vue 3 + Element Plus 封装单列控制编辑的可编辑表格组件

在Web应用开发中&#xff0c;经常需要提供表格数据的编辑功能。本文将介绍如何使用Vue 3结合Element Plus库来实现一个支持单列控制编辑功能的表格&#xff0c;并通过封装组件的形式提高代码的复用性。通过本教程&#xff0c;你将学会如何构建一个具备单列控制编辑功能的表格组…

Cloudways搭建WordPress外贸独立站完整教程(1)

验证邮件发送完成后&#xff0c;就等待Cloudways的回复邮件&#xff0c;一般24小时之内就会收到激活的邮件。 Cloudways账号升级 激活成功后还需要账户升级&#xff0c;Cloudways提供了为期3天的免费试用体验。如果在试用期结束之前未绑定信用卡以升级账户&#xff0c;试用期…

UE5学习笔记21-武器的射击功能

一、创建C类 创建武器子弹的类&#xff0c;创建生产武器子弹的类&#xff0c;创建弹壳的类&#xff0c;生产武器子弹的类的父类是武器的类 创建后如图&#xff0c;ProjectileMyWeapon类(产生子弹的类)继承自weapon类&#xff0c;Projectile(子弹的类)&#xff0c;Casing(弹壳声…

Claude 3.5:如何高效辅助编程——全面入门指南

在现代编程世界中&#xff0c;AI的角色越来越重要&#xff0c;尤其是在代码生成、调试、文档生成等领域中&#xff0c;AI工具的运用让开发者可以更高效地完成任务。Claude 3.5是一个这样的AI助手&#xff0c;凭借其强大的自然语言处理能力&#xff0c;在编程中提供了大量的支持…

Sui Narwhal and Tusk 共识协议笔记

一、Overwiew [ 整体流程: Client提交transaction到Narwhal Mempool。(Narwhal Mempool由一组worker和一个primary组成) Mempool接收到的Transaction->以Certificate的形式进行广播 由worker将交易打包为Batch,worker将Batch的hash发送给primary primary上运行了mempo…

mysql笔记4(数据类型)

数据库的数据类型应该是数据库架构师(DBA)和产品经理沟通后依据公司的项目、业务而定的&#xff0c;而且会不停地变化。数据类型的选择方面没有一个统一的标准&#xff0c;但是应该符合业务、项目的逻辑标准。 菜鸟教程 Mysql 数据类型 文章目录 1. int类型2. 浮点数3. 定点数4…

C# Dotfuscator加密dll设置流程

按照以下步骤处理后&#xff0c;反编译基本只能看到函数名&#xff0c;看不到源代码 1.Input 2.Setting 3.Rename 4.Rename 5.Control Flow 6.String Encryption 7.Output

【stata】自写命令分享dynamic_est,一键生成dynamic effect

1. 命令简介 dynamic_est 是一个用于可视化动态效应&#xff08;dynamic effect&#xff09;的工具。它特别适用于事件研究&#xff08;event study&#xff09;或双重差分&#xff08;Difference-in-Differences, DID&#xff09;分析。通过一句命令即可展示动态效应&#xf…

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求&#xff0c;要求做一款播放器&#xff0c;发现能力上跟EasyPlayer.js基本一致&#xff0c;满足要求&#xff1a; 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏&#xff08;单屏/全屏&#xff09; 多分屏&#xff08;2*2&#xff09; 多分屏…

JVM面试(七)G1垃圾收集器剖析

概述 上一章我们说了&#xff0c;G1收集器&#xff0c;它属于里程碑式的发展&#xff0c;开创了面向局部收集垃圾的概念。专门针对多核处理器以及大内存的机器。在JDK9中&#xff0c;更是呗指定为官方的GC收集器。满足高吞吐的通知满足GC的STW停顿时间尽可能的短。 虽然现在我…

恶意代码分析-Lab01-01

实验一 这个实验使用Lab01-01.exe和Lab01-01.d文件,使用本章描述的工具和技术来获取关于这些文件的信息。 问题: 将文件上传至 http:/www.VirusTotal.com/进行分析并查看报告。文件匹配到了已有的反病毒软件特征吗?这些文件是什么时候编译的?这两个文件中是否存在迹象说明它…

如何在docker容器中导入.sql文件

一、准备工作 确保容器运行&#xff1a; 首先确认包含 MySQL 服务的 Docker 容器正在运行。可以通过 docker ps 命令查看正在运行的容器列表。如果容器未运行&#xff0c;使用 docker start [container_id] 命令启动容器。 准备数据库文件&#xff1a; 将需要导入的数据库文件&…