LeetCode-刷题记录-滑动窗口合集(本篇blog会持续更新哦~)

一、滑动窗口概述

滑动窗口(Sliding Window)是一种用于解决数组(或字符串)中子数组(或子串)问题的有效算法。

在这里插入图片描述

Sliding Window核心思想:

滑动窗口技术的基本思想是维护一个窗口(一般是一个子数组或子串),该窗口在数组上滑动,并在滑动过程中更新窗口的内容。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

通过滑动窗口,可以在 ( O(n) ) 的时间复杂度内解决很多子数组(子串)问题,其中 ( n ) 是数组(字符串)的长度。

基本步骤:

  1. 初始化窗口: 定义一个窗口的起始位置和结束位置,通常是两个指针 leftright
  2. 滑动窗口: 不断地增加 right 指针来扩大窗口,直到窗口满足某个条件为止。

在这里插入图片描述

  1. 更新窗口: 一旦满足条件,尝试缩小窗口大小,即增加 left 指针,直到条件不满足为止。
  2. 记录结果: 在滑动窗口的过程中,根据题目要求来记录最终的结果。

二、习题合集

LeetCode 209 长度最小的子数组

在这里插入图片描述

  • 滑动窗口O(N)解法:
class Solution {public int minSubArrayLen(int target, int[] nums) {int n = nums.length;  // 数组的长度int ans = Integer.MAX_VALUE;  // 初始化结果为最大值,用于存储最短子数组的长度int l = 0;  // 左指针,指向滑动窗口的起始位置int sum = 0;  // 记录滑动窗口内元素的和for (int r = 0; r < n; r++) {  // 右指针,扩展滑动窗口sum += nums[r];  // 将右指针指向的元素加入窗口while (sum >= target) {  // 当窗口内元素和大于等于目标值时,尝试缩小窗口ans = Math.min(ans, r - l + 1);  // 更新最短子数组的长度sum -= nums[l];  // 缩小窗口,左指针向右移动,减少窗口内的元素和l++;  // 左指针右移}}return ans == Integer.MAX_VALUE ? 0 : ans;  // 如果找不到满足条件的子数组,返回0;否则返回最短子数组的长度}
}

LeetCode 3 无重复字符的最长子串

在这里插入图片描述


  • 第一版滑动窗口
class Solution {public int lengthOfLongestSubstring(String s) {Map<Character, Integer> map = new HashMap<>(); // 创建一个哈希表,用来记录字符及其出现的最后位置int n = s.length(); // 字符串的长度int l = 0, ans = 0; // l表示当前不重复子串的起始位置,ans用来记录最长不重复子串的长度for (int r = 0; r < n; r++) {char c = s.charAt(r); // 获取当前字符if (map.containsKey(c)) {//如果曾经出现的 字母 还在窗口内 —— l更新到 该位置+1//如果曾经出现的 字母 已不在当前窗口内了—— 则不需要更新l = Math.max(l,map.get(c)+1);}map.put(c, r); // 更新当前字符的最后出现位置为当前索引rans = Math.max(ans, r - l + 1); // 更新最长不重复子串的长度}return ans; // 返回最长不重复子串的长度}
}

要理解 left = Math.max(left,map.get(s.charAt(i)) + 1);需要回归到滑动窗口的原理上。

窗口中始终是无重复字母的字符串。 我们通过窗口的左界和右界控制窗口。

右界不用特意操作,因为它是+1,+1地涨上去,记得在循环里+1就好。

左界:每当有一个字符曾经出现过,就需要判断左界。

重点来了:

若,被判断的字符上一次出现的位置就在滑动窗口内,即 [ i,j ] 内, 则需要left改变位置,改变为该字符上次出现位置+1。也就是left = map.get(s.charAt(i)) + 1的情况。

例如:

abcdb中,窗口正常运行到abcd时,下一个字符为b,b上一次出现在实在窗口里,所以需要把left设置为上一次出现的位置+1的位置,得到新的窗口为cdb,不然你不这样设置,窗口里有重复的字符(bcdb),不符合窗口的定义。

若,不在滑动窗口内,则不用管。 不用管是因为:窗口中字符串没有重复字符。窗口符合定义。所以left = left。 left = left就表示这个窗口暂时不变。

在这里插入图片描述


  • 第二版优化的滑动窗口:
class Solution {public int lengthOfLongestSubstring(String s) {// 记录字符上一次出现的位置int[] last = new int[128]; // 创建一个长度为128的整型数组,用来记录ASCII码表中每个字符上一次出现的位置for(int i = 0; i < 128; i++) {last[i] = -1; // 初始化数组,所有字符的上一次出现位置都设为-1,表示尚未出现过}int n = s.length(); // 字符串s的长度int res = 0; // 用于记录最长的不重复子串的长度int start = 0; // 窗口开始位置,用来维护当前不重复子串的起始位置for(int i = 0; i < n; i++) {int index = s.charAt(i); // 获取当前字符的ASCII码作为索引start = Math.max(start, last[index] + 1); // 更新窗口的起始位置,确保不重复的起点res = Math.max(res, i - start + 1); // 更新最大的不重复子串长度last[index] = i; // 更新当前字符的最后出现位置为当前索引i}return res; // 返回最长的不重复子串的长度}
}

LeetCode 187 重复的DNA序列

在这里插入图片描述

  • 哈希表法~
class Solution {public List<String> findRepeatedDnaSequences(String s) {List<String> ans = new ArrayList<>(); // 用于存放重复的DNA序列int n = s.length(); if (n < 10) return ans; // 如果字符串长度小于10,直接返回空列表,因为无法形成长度为10的序列Map<String, Integer> map = new HashMap<>(); // 创建一个哈希表,用来记录每个长度为10的子序列及其出现的次数map.put(s.substring(0, 10), 1); // 初始化,将第一个长度为10的子序列放入哈希表中for (int i = 1; i + 10 <= n; i++) { // 从第二个子序列开始遍历到倒数第十个子序列String ss = s.substring(i, i + 10); // 获取当前长度为10的子序列if (map.getOrDefault(ss, 0) == 1) { // 如果该子序列已经在哈希表中出现过一次ans.add(ss); // 将该子序列加入结果列表}map.put(ss, map.getOrDefault(ss, 0) + 1); // 更新哈希表中该子序列的出现次数}return ans; // 返回重复的DNA序列列表}
}
  • 滑动窗口法~
class Solution {// 滑动窗口法查找重复的长度为10的DNA序列public List<String> findRepeatedDnaSequences(String s) {List<String> ans = new ArrayList<>(); // 用于存放重复的DNA序列int n = s.length(); // 字符串的长度if (n < 10) return ans; // 如果字符串长度小于10,直接返回空列表,因为无法形成长度为10的序列StringBuilder sb = new StringBuilder(s.substring(0, 10)); // 初始化第一个长度为10的子串Set<String> set = new HashSet<>(); // 使用集合来记录出现过的子串set.add(sb.toString()); // 将第一个子串添加到集合中for (int i = 1; i + 10 <= n; i++) {String str = s.substring(i, i + 10); // 获取当前长度为10的子串if (set.contains(str)) { // 如果集合中已经包含当前子串if (!ans.contains(str)) // 且列表中还未包含该子串ans.add(str); // 将该子串添加到列表中} else { // 如果集合中不包含当前子串set.add(str); // 将当前子串添加到集合中}}return ans; // 返回存放了重复DNA序列的列表}
}

LeetCode 424 替换后的最长重复字符

在这里插入图片描述
在这里插入图片描述

  • 核心思想:

相同的最长子字符串(窗口) = 窗口内最大字符个数 + 反转次数

一旦 窗口长度 - 窗口内最大字符个数 > 反转次数 窗口开始移动

public int characterReplacement(String s, int k) {int n = s.length();if(n<2) return n;int ans = 0; // 用于存储最长连续相同字符的子串的长度int maxFreq = 0; // 用于存储当前窗口内出现次数最多的字符的次数char[] c = s.toCharArray();int[] freq = new int[26]; // 记录当前窗口内每个字符出现的次数int left = 0; // 滑动窗口的左边界for (int right = 0; right < n; right++) {++freq[c[right] - 'A']; // 更新右边界字符的出现次数maxFreq = Math.max(maxFreq, freq[c[right] - 'A']); // 更新最大出现次数// 如果当前窗口的大小减去出现次数最多的字符的次数大于k,则需要缩小窗口// 使得窗口内可以通过替换字符使其变成连续相同字符的子串if (right - left + 1 > maxFreq + k) {freq[c[left] - 'A']--; // 缩小窗口时,更新左边界字符的出现次数left++; // 缩小窗口}// 更新最长连续相同字符的子串的长度ans = Math.max(ans, right - left + 1);}return ans;}


更新于:

在这里插入图片描述

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

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

相关文章

怎样在Python中使用oobabooga的API密钥,通过端口5000获取模型列表的授权

题意&#xff1a; oobabooga-textgen-web-ui how to get authorization to view model list from port 5000 via the oobas api-key in python 怎样在Python中使用oobabooga的API密钥&#xff0c;通过端口5000获取模型列表的授权 问题背景&#xff1a; I wish to extract an…

fastapi+vue3前后端分离开发第一个案例整理

开发思路 1、使用fastapi开发第一个后端接口 2、使用fastapi解决cors跨域的问题。cors跨域是浏览器的问题&#xff0c;只要使用浏览器&#xff0c;不同IP或者不同端口之间通信&#xff0c;就会存在这个问题。前后端分离是两个服务&#xff0c;端口不一样&#xff0c;所以必须要…

XLSX + LuckySheet + LuckyExcel实现前端的excel预览

文章目录 功能简介简单代码实现效果参考 功能简介 通过LuckyExcel的transformExcelToLucky方法&#xff0c; 我们可以把一个文件直接转成LuckySheet需要的json字符串&#xff0c; 之后我们就可以用LuckySheet预览excelLuckyExcel只能解析xlsx格式的excel文件&#xff0c;因此对…

.NET 漏洞分析 | 某ERP系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

学习笔记——动态路由——OSPF(认证)

十二、OSPF邻居认证 1、OSPF邻居认证概述 链路是路由器接口的另一种说法&#xff0c;因此OSPF也称为接口状态路由协议。OSPF通过路由器之间通告网络接口的状态来建立链路状态数据库&#xff0c;生成最短路径树&#xff0c;每个OSPF路由器使用这些最短路径构造路由表。 OSPF认…

基于Vue框架实现的记事本

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>懒人记事本</title><style>body {fo…

深度网络现代实践 - 深度前馈网络之反向传播和其他的微分算法篇

序言 反向传播&#xff08;Backpropagation&#xff0c;简称backprop&#xff09;是神经网络训练过程中最关键的技术之一&#xff0c;尤其在多层神经网络中广泛应用。它是一种与优化方法&#xff08;如梯度下降法&#xff09;结合使用的算法&#xff0c;用于计算网络中各参数的…

如何计算弧线弹道的落地位置

1&#xff09;如何计算弧线弹道的落地位置 2&#xff09;Unity 2021 IL2CPP下使用Protobuf-net序列化报异常 3&#xff09;编译问题&#xff0c;用Mono可以&#xff0c;但用IL2CPP就报错 4&#xff09;Wwise的Bank在安卓上LoadBank之后&#xff0c;播放没有声音 这是第393篇UWA…

02 数据加工层 如何搭建用户与内容的标准规范体系

你好&#xff0c;我是周大壮。 01 讲我们提到了个性化流量分发体系的四个阶段&#xff0c;并着重讲解了数据采集阶段的内容。那么&#xff0c;这一讲我们主要围绕数据加工阶段的内容进行详细讲解。 在课程开始之前&#xff0c;我们先举一个场景进行说明。 近年来&#xff0c…

静态方法与实例方法的区别

静态方法与实例方法的区别 1、静态方法&#xff08;Static Methods&#xff09;1.1 调用方式1.2 访问权限 2、实例方法&#xff08;Instance Methods&#xff09;2.1 调用方式2.2 访问权限 3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1…

【C++】解决 C++ 语言报错:Invalid Array Index

文章目录 引言 无效数组索引&#xff08;Invalid Array Index&#xff09;是 C 编程中常见且危险的错误之一。当程序试图使用不合法的索引访问数组时&#xff0c;就会发生无效数组索引错误。这种错误不仅会导致程序崩溃&#xff0c;还可能引发不可预测的行为和安全漏洞。本文将…

【PB案例学习笔记】-28制作一个右键菜单

写在前面 这是PB案例学习笔记系列文章的第28篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

任天堂称未来第一方游戏不会使用生成式AI

虽然EA、育碧、暴雪、Embracer等西方游戏厂商都大力支持生成式AI技术&#xff0c;但日本老牌游戏公司任天堂并不会追随这一步伐。任天堂已经确认该公司未来的第一方游戏不会使用生成式AI技术。 在公司最近的投资人问答会上&#xff0c;任天堂描绘了公司未来游戏愿景。在谈到AI技…

LeetCode——第 404 场周赛

周赛 三角形的最大高度 给你两个整数 red 和 blue&#xff0c;分别表示红色球和蓝色球的数量。你需要使用这些球来组成一个三角形&#xff0c;满足第 1 行有 1 个球&#xff0c;第 2 行有 2 个球&#xff0c;第 3 行有 3 个球&#xff0c;依此类推。 每一行的球必须是 相同 …

Go语言--自定义函数

定义格式 函数构成代码执行的逻辑结构。在 Go语言中&#xff0c;兩数的基本组成为:关键字 func、函数名、参数列表、返回值、所数体和返回语句。 函数定义说明: func:函数由关键字func开始声明FuncName:函数名称&#xff0c;根据约定&#xff0c;数名首字母小写即为private…

浅谈 Linux 中的 core dump 分析方法

文章目录 一、什么是 core dump二、发生 core dump 的原因1. 空指针或非法指针引起 core dump2. 数组越界或指针越界引起的 core dump3. 数据竞争导致 core dump4. 代码不规范 三、core dump 分析方法1. 启用 core dump2. 触发 core dump2-1. 因空指针解引用而崩溃2-2. 通过 SI…

图形编辑器基于Paper.js教程06:鼠标画圆与椭圆

绘制椭圆与圆形&#xff1a;利用Paper.js进行交互式图形设计 在Web应用中实现交互式图形绘制功能&#xff0c;对于提高用户体验至关重要&#xff0c;尤其是在设计和艺术相关的应用中。Paper.js是一款强大的JavaScript库&#xff0c;专门用于处理矢量图形&#xff0c;它提供了一…

智能语音门锁:置入NV170D语音芯片ic 打造便捷生活新体验

一、智能门锁语音芯片开发背景 随着科技的飞速发展&#xff0c;传统门锁的局限性日益凸显&#xff0c;无法满足现代人对高效、安全生活的需求。在这样的时代背景下&#xff0c;智能门锁应运而生&#xff0c;它不仅继承了传统门锁的基本功能&#xff0c;更通过融入先进的科技元素…

商标的近似分辩,商标起名称时注意!

曾有过网友发来商标名称&#xff0c;普推知商标老杨说有近似&#xff0c;然后网友起过新名称还是存有近似&#xff0c;或者加字&#xff0c;后面加的通用词&#xff0c;与先有商标名称也是近似。 “良信健康”这个名称健康是行业通用词&#xff0c;加成健康后变成四个字&#x…

HTTP协议深入

1.了解web和网络基础 有客户端和服务端双方参与交互 客户端发送请求:request 服务端根据请求给出响应:response 请求通过URL来指定要获取都得资源 响应内容可以是HTML网页&#xff0c;或者用json表示的数据或者其他二进制文件内容 Web使用一种名为HTTP的协议作为规范&…