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

【刷题笔记】之滑动窗口(长度最小的子数组、水果成篮、最小的覆盖子串)

滑动窗口模板

//滑动窗口模板:注意使用滑动窗口方法,使用一个 for(while) 循环中的变量是用来控制终止位置的//最小滑窗:给定数组 nums,定义滑动窗口的左右边界 i、j,求满足某个条件的滑窗的最小长度
for(j = 0; j < nums.length; ++j) {不断的添加值到题中要求的结果集中(比如 sum)while(满足条件) {更新求最小长度 result = Math.min(result,j-i+1);不断更新结果集(比如 sum)i++; // 缩小左边界}
}//最大滑窗:给定数组 nums,定义滑窗的左右边界 i、j,求满足某个条件的滑窗的最大长度
for(j = 0; j < nums.length; ++j) {不断的添加值到题中要求的结果集中(比如 sum)while(不满足条件) {i++; // 缩小左边界不断更新结果集(比如 sum)}// 走到这里条件满足,更新最小长度,继续 for 循环更新求最小长度 result = Math.min(result,j-i+1);
}

1. 长度最小的子数组

题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

1 <= target <= 109

1 <= nums.length <= 105

1 <= nums[i] <= 105

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

思想:

滑动窗口就是不断的调节子序列的起始位置和终止位置,从而得出想要的结果

使用暴力解法,是一个 for 循环滑动窗口的起始位置,一个 for 循环为滑动窗口的终止位置,用两个 for 循环完成一个不断搜索区间的过程。

而滑动窗口是用一个 for 循环来完成这个操作,并且这个 for 表示的应该是终止位置

因为,如果这个 for 表示的是起始位置,那么如何遍历剩下的终止位置呢,到最后还是又回到了暴力解法

所以 滑动窗口,使用一个 for 循环来表示滑动窗口的终止位置

使用滑动窗口需要确定三点:

窗口内是什么?
窗口就是满足 sum >= targe 长度的最小的连续子数组
如何移动窗口的起始位置
起始位置就是 如果当前窗口的值大于 targe,窗口就要向前移动了(缩小范围)
如何移动窗口的结束位置
结束位置就是 for 循环中的索引

滑动窗口的优点在于能够根据当前子序列和大小的情况,不断调节子序列的起始位置,在这道题中也就是满足sum >= target 时起始位置就要开始移动,从而将 O(n^2) 暴力解法时间复杂度降为 O(n)

滑动窗口

    // 209public int minSubArrayLen(int target, int[] nums) {int i = 0; //左int result = Integer.MAX_VALUE;int sum = 0;for (int j = 0; j < nums.length; j++) { // 右sum += nums[j];while(sum >= target) { // while 循环找到满足要求且元素个数最小的result = Math.min(result,j-i+1);sum -= nums[i++];}}return result == Integer.MAX_VALUE ? 0 : result;}

2. 水果成篮

题目链接:904. 水果成篮 - 力扣(LeetCode)

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。

你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。

一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

示例 3:

输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

提示:

1 <= fruits.length <= 105

0 <= fruits[i] < fruits.length

思想:

在上一题长度最小的子数组中是要求满足条件的子数组的最小长度,用滑动窗口的方法来说,就是最小滑窗是在迭代右移左边界的过程中更新结果。

而本道题水果成篮是要求满足条件情况下收集水果的最大数目,也就是要在迭代右移右边界的过程中更新结果

利用 left 和 right 分别表示窗口的左右边界,同时利用哈希表来存储这个窗口内的数以及出现的次数,一个 for 循环控制的就是终止位置也就是右边界,右移一个位置,并且将 fruits[right] 加入到哈希表中,如果 哈希表大小大于2(也就是水果的种类),那就移动 left 将 fruits[left] 从哈希表中移除,直到满足要求,并且当 fruits[left] 在哈希表中出现的次数减少为0,那就将 key 移除

代码:

public int totalFruit(int[] fruits) {int n = fruits.length;Map<Integer,Integer> cnt = new HashMap<>();int left = 0, ans = 0;for(int right = 0; right < n; ++ right) {// 每次添加一个水果计数cnt.put(fruits[right],cnt.getOrDefault(fruits[right],0) + 1);// 如果添加新水果后,不止两种,就从前往后逐渐丢弃水果while(cnt.size() > 2) {int pre = fruits[left++];cnt.put(pre,cnt.get(pre) - 1);// 如果这种水果被全部丢弃,就从 map 中删除if(cnt.get(pre) == 0) {cnt.remove(pre);}}// 计算一下当前区域的长度ans = Math.max(ans,right-left+1);}return ans;
}

3. 最小的覆盖子串

题目链接:76. 最小覆盖子串 - 力扣(LeetCode)

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。

  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:

  • m == s.length

  • n == t.length

  • 1 <= m, n <= 105

  • s 和 t 由英文字母组成

**进阶:**你能设计一个在 o(m+n) 时间内解决此问题的算法吗?

思想:

还是按滑动窗口的思路来做

  1. 不断增加 j 使滑动窗口增大,直到窗口包含了 T 中所有元素

  1. 不断增加 i 使用滑动窗口缩小,因为是要求最小子串,所以要将不必要的元素排除在外,使用长度减小,直到遇到一个必须包含的元素,那么此时就记录这个滑动窗口的长度,并且保存最小值(也就是保存左边界,然后可以根据长度计算右边界,从而可以返回子串)

  1. 让 i 再向右移动一个位置,那么这个时候滑动窗口肯定是不满足条件的,就重新从步骤1 开始执行,寻找新的满足条件的滑动窗口

判断滑动窗口中包含了 T 的所有元素

这里可以用一个字典 need 也就是数组来表示滑动窗口中需要的各个元素的数量,int[] need = new int[128] 这个数组大小设为 128 是因为 ascii 中有 128 个字符,比如 need[76] = 2,表示 ascii 为 76 的这个字符,在字符串中需要两个,比如 need[76] = -2,表示 ascii 为 76 的这个字符,在字符串中多余两个。

先把用 T 把 need 数组初始化,表示现在need[X] = ? 需要这些元素,下面就是通过滑动窗口来修改need 数组中的元素,当滑动窗口中包含某个元素,就让 need 元素减1,代表需要的元素减1,当滑动窗口移除某个元素,就让 need 中元素的数量加1,这样做的目的就是为了步骤2中的 排除不必要元素,数量为负表示不必要元素,数量为 0 表示刚刚好

need 数组中记录着当前滑动窗口中,需要的元素数量,这个动态修改是靠滑动窗口的移动来维护的

总之,如何判断滑动窗口中包含了 T 的所有元素,这是根据 need 中所有元素的数量都小于或等于 0 时,表示当前滑动窗口不需要任何元素

但是还有个细节,每次判断滑动窗口是否包含 T 的所有元素,都是去判断 need 所有元素数量都小于等于0,这样还是要遍历 need 的,这个是要耗费时间的,所以可以**定义一个变量 needCnt 来记录当前需要元素的总数量,**当遇到所需元素 c,那 need[c] 就减1,同时 needCnt 也减1,这样就不用每次都来遍历 need 数组了,只需要看 needCnt 就行

代码:

public String minWindow(String s, String t) {// need 数组表示每个字符在 t 中需要的数量// need[76]=2 表示 ascii为76的字符在目标字符串中需要两个int[] need = new int[128];// 用 t 来初始化 need 【初始状态】for(int i = 0; i < t.length(); i++) {need[t.charAt(i)]++;}/*left/right: 窗口左右边界size: 表示窗口的长度needCnt: 表示当前所需字符的总数,起始大小为 t 的长度start:表示有效窗口的起始位置,可以根据size,来求子串区间范围*/int left = 0, size = Integer.MAX_VALUE, needCnt = t.length(), start = 0;for(int right = 0; right < s.length(); right++) {char c = s.charAt(right);// 【步骤一】// 如果当前这个字符 c 在 t 中存在那么 need 中对应位置应该是大于 0if(need[c] > 0) {needCnt--;  // 找到一个元素了,所需字符总数-1}// 不论这个字符是否在 t 中都要 -1.need[c]--;if(needCnt == 0) {// 【步骤二】// 缩小左边界,去除无用的元素while(left < right && need[s.charAt(left)] < 0) {need[s.charAt(left)]++;left++;}// 更新窗口的长度if(right - left + 1 < size) {size = right - left + 1;start = left;}// 【步骤三】need[s.charAt(left)]++;left++;needCnt++;}}return size == Integer.MAX_VALUE ? "" : s.substring(start,start+size);
}

相关文章:

【刷题笔记】之滑动窗口(长度最小的子数组、水果成篮、最小的覆盖子串)

滑动窗口模板//滑动窗口模板&#xff1a;注意使用滑动窗口方法&#xff0c;使用一个 for(while) 循环中的变量是用来控制终止位置的//最小滑窗&#xff1a;给定数组 nums&#xff0c;定义滑动窗口的左右边界 i、j&#xff0c;求满足某个条件的滑窗的最小长度 for(j 0; j < …...

【JavaScript速成之路】JavaScript函数

&#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;【JavaScript速成之路】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 文章目录前言1&#xff0c;函数基础1.1&#xff0c;函数概念1.2&#xff0c;函数使用1.3&…...

萤火虫算法优化SVM变压器故障分类预测,fa-svm分类预测,libsvm参数优化

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 SVM应用实例,基于fa-svm分类预测 代码 结果分析 展望 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是…...

JavaScript DOM API的使用

文章目录一. 什么是DOM二. 最常用的DOM API1. 选中页面元素2. 操作元素的属性2.1 事件概念2.2 获取/修改元素内容计数器2.4 获取/修改元素属性点击图片切换2.5 获取/修改表单元素属性表单计数器全选/取消全选按钮2.6 获取修改样式属性点击文字放大实现夜间/日间模式的切换3. 操…...

Vue组件库出现$listeners is readonly等错误的原因及预防方法

本文主要是面向写组件库的人士&#xff0c;而不是组件库的使用人士。 出现原因 根本原因是因为组件库的package.json中 dependencies包含了vue包&#xff0c;然后导致最后打包出来的组件库也包含vue包 然后和引用这个组件库的项目中的vue发生冲突。 举个例子&#xff0c;pro…...

lsusb

用法&#xff1a; lsusb -hUsage: lsusb [options]... List USB devices -v, --verbose Increase verbosity (show descriptors) -s [[bus]:][devnum] Show only devices with specified device and/or bus numbers (in decimal) -d vendor:[product] …...

Allegro如何在PCB中添加层面操作指导

Allegro如何在PCB中添加层面操作指导 在用Allegro做PCB设计的时候,根据需要,会在PCB中额外添加一些额外的层面,如下图 如何添加,具体操作如下 点击Setup点击Subclasses...

淘宝widget链路方案总结

目前widget生态已经做了大量的基建工作,同时在widget生态的演进过程中我们发现如何匹配用户的偏好一直以来是一个挑战工作&#xff0c;本文介绍了widget的整体链路。业务背景▐ widget介绍2020年底iOS推出了新版widget之后引起了一些声浪&#xff0c;但仍然很多苹果用户并不了…...

c++指针

内存地址 将内存抽象成一个很大的一维字符数组&#xff0c;编码就是对内存的每一个字节分配一个32位或64位的二进制编号。这个内存编号称之为内存地址&#xff08;唯一&#xff09;&#xff0c;内存中的每一个数据都会分配相应的地址。 #include<iostream> using namesp…...

Qt 贴图实现方向控制盘

一、效果走一波 二、使用贴图进行不规则按钮的设计与开发 开发环境描述&#xff1a;QtCreator Qt Desinger &#xff08;1&#xff09;首先准备待贴的图片 ​ 图片的切片大小必须一样&#xff0c;背景为透明的&#xff1b;将待贴的所有图片都切下来&#xff0c;文件标明名称…...

建模杂谈系列211 ADBS的取数模式以及衔接

说明 这应该是进一步的完善ADBS的工作模式。 之所以做A系列的架构工具&#xff0c;就是为了可以实现大型的数据处理、存储。从应用上说&#xff0c;是为了提高效率&#xff0c;并达到超高的效果。 为了达到这个目的&#xff0c;就必须从数据架构上、任务调度上、逻辑架构上作…...

易基因:RRBS揭示晚年锻炼可以减缓骨骼肌表观遗传衰老(甲基化年龄)|新研究

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。2021年12月21日&#xff0c;美国阿肯色大学、德克萨斯大学和肯塔基大学的研究人员合作在《Aging Cell》杂志发表了题为“Late-life exercise mitigates skeletal muscle epigenetic aging”…...

JVM的基本知识

JVM JVM是java的虚拟机,是一个十分复杂的东西,所以掌握的要求比较高.本文主要是研究JVM的三大话题 JVM内存划分JVM类加载JVM的垃圾回收 JVM内存划分 java程序要执行的时候,JVM会先申请一块空间,这里就涉及到JVM的内存划分 堆 : 放的是new 出来的对象栈: 放的是方法之间的调…...

STM32移植FreeRTOS操作系统

一、FreeRTOS源码下载&#xff08;1&#xff09;移植钱得准备前菜对吧&#xff0c;我们先来去官网瞄一瞄网址&#xff1a;https://freertos.org/zh-cn-cmn-s/ 第一步&#xff1a;点击下载FreeRTOS第二步&#xff1a;选择版本下载&#xff08;我选择稳定版本&#xff09;注&…...

【专项训练】泛型递归、树的递归

递归和循环没有明显的边界! 不要进行人肉递归! 找最近重复子问题,直接写递归! 数学归纳法思维:1,2,…… 70. 爬楼梯 https://leetcode.cn/problems/climbing-stairs/ 互斥,且加在一起是全部答案! 动态规划法:用数组做递推,就是动态规划!!! class Solution...

React18 setState是同步还是异步?

相信大家对于react的setState肯定是不陌生了, 这是一个用于更新状态的函数. 但是在之前有一道非常经典的面试题就是关于setState是同步还是异步的问题, 具体可以参考我之前写的一篇文章: 一篇文章彻底理解setState是同步还是异步&#xff01;. 对于react 18之前的版本, 上文说的…...

Kafka消费者 TCP管理

Kafka消费者 TCP管理创建 TCPFindCoordinator连接协调者消费数据TCP 连接数关闭 TCP 连接消费者的程序入口类是 KafkaConsumer 构建 KafkaConsumer 时 &#xff0c;不会创建任何 TCP 连接TCP 连接是用 KafkaConsumer.poll 创建 创建 TCP poll 创建 TCP 的地方 : 发起 FindC…...

软考高级备考哪一个类型好些?

软考高级是比中级和初级难&#xff0c;科目就要考三科&#xff0c;选择题基础知识简答题案例分析写作论文 软考高级科目有&#xff1a;信息系统项目管理师、系统分析师、系统架构设计师、网络规划师、系统规划与管理师。如下&#xff1a; 软考高级中高项信息系统项目管理师师比…...

2023 HBU 天梯赛第一次测试 题目集

目录 1 建校日期 2 发射小球 3 背上书包去旅行 4 吉利的数字 5 向前走 6 热水器 7 走方格 8 朋友圈 9 交保护费 10 走方格 11 和与积 12 缩短字符串 13 买木棒 1 建校日期 在2022 ICPC沈阳站上&#xff0c;东北大学命题组给参赛的选手们出了一道签到题&#xff0…...

华为OD机试题,用 Java 解【子序列长度】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

内网环境解决SSL证书问题

本来这个没什么好写的&#xff0c;但是坑实在有点多&#xff0c;不得不写个文章记录下来。 创建证书看这里&#xff01;&#xff01;&#xff01; 很多知识点要结合这个页面内容来看。 创建证书已经看过相关文章&#xff0c;然后用unity跑的时候发现连不上&#xff0c;完全没…...

数据分析方法01对比分析法

对比分析法 1、概念 基于相同的数据标准下&#xff0c;把两个及以上相互联系的指标数据进行比较&#xff0c;准确量化的分析他们的差异&#xff0c;说明研究对象在规模大小&#xff0c;水平高低&#xff0c;速度快慢等的不同表现&#xff0c;目的是为了找到差异的原因&#x…...

基于SMOKE多模式排放清单处理技术及EDGAR/MEIC清单制作与VOCs排放量核算

查看原文>>>基于SMOKE多模式排放清单处理技术及EDGAR/MEIC清单制作与VOCs排放量核算 (qq.com)随着我国经济快速发展&#xff0c;我国面临着日益严重的大气污染问题。近年来&#xff0c;严重的大气污染问题已经明显影响国计民生&#xff0c;引起政府、学界和人们越来越…...

CSS流动布局-页面自适应

项目中经常会碰到页面自适应的问题&#xff0c;例如&#xff1a;商城的列表展示、分类列表展示等页面&#xff0c;如下&#xff1a; 该页面会随着页面的放大缩小而随之发生变化&#xff0c;这种自适应的页面布局在大屏幕、小屏幕、不同的浏览器设备上都应该呈现出与设计匹配的…...

3.Elasticsearch初步进阶

3.Elasticsearch初步进阶[toc]1.文档批量操作批量获取文档数据批量获取文档数据是通过_mget的API来实现的在URL中不指定index和type请求方式:GET请求地址:_mget功能说明:可以通过ID批量获取不同index和type的数据请求参数docs:文档数组参数_index:指定index_type:指定type_id:指…...

优思学院|六西格玛管理的核心理念是什么?

六西格玛管理是一种基于数据分析的质量管理方法&#xff0c;旨在通过降低过程的变异性来达到质量稳定和优化的目的。该方法以希腊字母“σ”为名&#xff0c;代表标准差&#xff0c;是衡量过程变异性的重要指标。 六西格玛管理的核心理念是“以客户为中心、以数据为基础、追求…...

第十七节 多态

多态 什么是多态? ●同类型的对象&#xff0c;执行同一个行为&#xff0c;会表现出不同的行为特征。 多态的常见形式 父类类型 对象名称new子类构造器; 接口 对象名称new 实现类构造器; 多态中成员访问特点 ●方法调用:编译看左边&#xff0c;运行看右边。 ●变量调用:编译看…...

[vue]提供一种网站底部备案号样式代码

演示 vue组件型&#xff08;可直接用&#xff09; 组件代码&#xff1a;copyright-icp.vue <template><div class"icp">{{© ${year} ${author} }}<a href"http://beian.miit.gov.cn/" target"_blank">{{ record }}</a…...

python第四天作业~函数练习

目录 作业4、判断以下哪些不能作为标识符 A、a B、&#xffe5;a C、_12 D、$a12 E、false F、False 作业5&#xff1a; 输入数&#xff0c;判断这个数是否是质数&#xff08;要求使用函数 for循环&#xff09; 作业6&#xff1a;求50~150之间的质数是…...

linux安装influxdb-rpmyum方式

一、influxdb的安装InfluxDB简介时序数据库InfluxDB版是一款专门处理高写入和查询负载的时序数据库&#xff0c;用于存储大规模的时序数据并进行实时分析&#xff0c;包括来自DevOps监控、应用指标和IoT传感器上的数据主要特点&#xff1a;专为时间序列数据量身订造高性能数据存…...