算法体系-25 第二十五节:窗口内最大值或最小值的更新结构

一 滑动窗口设计知识点

滑动窗口是什么?

滑动窗口是一种想象出来的数据结构: 滑动窗口有左边界L和有边界R 在数组或者字符串或者一个序列上,记为S,窗口就是S[L..R]这一部分 L往右滑意味着一个样本出了窗口,R往右滑意味着一个样本进了窗口 L和R都只能往右滑

滑动内最大值和最小值的更新结构

窗口不管L还是R滑动之后,都会让窗口呈现新状况, 如何能够更快的得到窗口当前状况下的最大值和最小值? 最好平均下来复杂度能做到O(1) 利用单调双端队列!

1.1 概念

任何时候l和r都可以往右动,遵循的原则L不能大于R,R不能大于数组的右侧边界 L和R不能回退

二 求每次形成窗口的最大值

可以在每次形成窗口的时候遍历窗口的数据求最大值

三 设计一个任何情况下端口的最大值

使用双端队列,队列遵循的原则是从头部到尾部的值是从大到小的更新策略,不管队列里面的值出去是从头部还是尾部出,一旦出去了就不再找回

1 R往右动的时候,队列动的规则是,当新进来的值比前面的值小直接从尾部进,当新进来的值比队列里面的值大,先从尾部弹出队列的值其不要了,再把大于他的值压进去

3.1  R阔的情况

L的只能往右,在双端队列里面,为什么在R往右阔的时候,当前值比队列里面的值大的时候可以将之前进去的时抛弃掉,因为根据l和r只能往右阔,我当前的值是晚进来的,我一定是比刚从队列里面出去的值是晚过期的,所以可以这样做更新策略

二 双端队列减的情况也就是L阔的情况

看双端队列里面的下标是否过期,过期的话就从头部弹出

更新的时间复杂度

二 一个固定大小为W的窗口的最大值

2.1 描述

假设一个固定大小为W的窗口,依次划过arr, 返回每一次滑出状况的最大值 例如,arr = [4,3,5,4,3,3,6,7], W = 3 返回:[5,5,5,4,6,7]

2.2 分析

分析应该收集的长度

流程分析

2.3 代码

package class24;import java.util.LinkedList;public class Code01_SlidingWindowMaxArray {// 暴力的对数器方法public static int[] right(int[] arr, int w) {if (arr == null || w < 1 || arr.length < w) {return null;}int N = arr.length;int[] res = new int[N - w + 1];int index = 0;int L = 0;int R = w - 1;while (R < N) {int max = arr[L];for (int i = L + 1; i <= R; i++) {max = Math.max(max, arr[i]);}res[index++] = max;L++;R++;}return res;}public static int[] getMaxWindow(int[] arr, int w) {if (arr == null || w < 1 || arr.length < w) {return null;}// qmax 窗口最大值的更新结构// 放下标LinkedList<Integer> qmax = new LinkedList<Integer>();int[] res = new int[arr.length - w + 1];int index = 0;for (int R = 0; R < arr.length; R++) {while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]) {qmax.pollLast();}qmax.addLast(R);if (qmax.peekFirst() == R - w) {qmax.pollFirst();}if (R >= w - 1) {res[index++] = arr[qmax.peekFirst()];}}return res;}// for testpublic static int[] generateRandomArray(int maxSize, int maxValue) {int[] arr = new int[(int) ((maxSize + 1) * Math.random())];for (int i = 0; i < arr.length; i++) {arr[i] = (int) (Math.random() * (maxValue + 1));}return arr;}// for testpublic static boolean isEqual(int[] arr1, int[] arr2) {if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {return false;}if (arr1 == null && arr2 == null) {return true;}if (arr1.length != arr2.length) {return false;}for (int i = 0; i < arr1.length; i++) {if (arr1[i] != arr2[i]) {return false;}}return true;}public static void main(String[] args) {int testTime = 100000;int maxSize = 100;int maxValue = 100;System.out.println("test begin");for (int i = 0; i < testTime; i++) {int[] arr = generateRandomArray(maxSize, maxValue);int w = (int) (Math.random() * (arr.length + 1));int[] ans1 = getMaxWindow(arr, w);int[] ans2 = right(arr, w);if (!isEqual(ans1, ans2)) {System.out.println("Oops!");}}System.out.println("test finish");}}

二 子数组中和小于sum的个数

2.1 描述

给定一个整型数组arr,和一个整数num 某个arr中的子数组sub,如果想达标,必须满足: sub中最大值 – sub中最小值 <= num, 返回arr中达标子数组的数量

2.2 分析 暴力

2.3 滑动窗口解析分析   

结论1 L到R范围内达标,那么它内部子数组也达标

一个 max-min范围的值小于sum可以推出 该max和min更小范围的子数组也大标,因为范围缩小了范围更靠近最后的差值更小

结论二 R到L范围不达标,那么l往左或者R往右也一定不达标

2.4 分析该题过程

一 两个队列 Qmax和 Qmin

二 滑动窗口的过程中会实时更新Qmax和 Qmin,当Qmax- Qmin 满足条件此时可以算出这个子数组满足条件的个数(由上面的两个结论推出)

三 接着l往右阔一个重复上面的过程

过期操作设置

//这块的过期是因为上面的l要开始++操作,滑出了窗口,但是在maxWindow,minWindow里面存的index正好是当前的l,那么下次++后这次就就要移除
if (maxWindow.peekFirst() == L) {
maxWindow.pollFirst();
}
if (minWindow.peekFirst() == L) {
minWindow.pollFirst();
}

2.5 代码

public static int num(int[] arr, int sum) {if (arr == null || arr.length == 0 || sum < 0) {return 0;}int N = arr.length;int count = 0;LinkedList<Integer> maxWindow = new LinkedList<>();LinkedList<Integer> minWindow = new LinkedList<>();int R = 0;for (int L = 0; L < N; L++) {//【l .....//[l.....r (初次不达标了停止)while (R < N) {while (!maxWindow.isEmpty() && arr[maxWindow.peekLast()] <= arr[R]) {maxWindow.pollLast();}maxWindow.addLast(R);while (!minWindow.isEmpty() && arr[minWindow.peekLast()] >= arr[R]) {minWindow.pollLast();}minWindow.addLast(R);if (arr[maxWindow.peekFirst()] - arr[minWindow.peekFirst()] > sum) {break;} else {R++;}}count += R - L;//这块的过期是因为上面的l要开始++操作,滑出了窗口,但是在maxWindow,minWindow里面存的index正好是当前的l,那么下次++后这次就就要移除if (maxWindow.peekFirst() == L) {maxWindow.pollFirst();}if (minWindow.peekFirst() == L) {minWindow.pollFirst();}}return count;}

三 加油站的良好出发点问题

3.1 描述

3.2 分析

将上面的数组进行加工,根据题目题目要求只要由不掉到0以下就行,就有当前加油站到下一个加油站的距离减去要耗的油,当当前数是否不小于0就表示满足题目要求

3.3 代码

package class24;import java.util.LinkedList;// 测试链接:https://leetcode.com/problems/gas-station
public class Code03_GasStation {// 这个方法的时间复杂度O(N),额外空间复杂度O(N)public static int canCompleteCircuit(int[] gas, int[] cost) {boolean[] good = goodArray(gas, cost);for (int i = 0; i < gas.length; i++) {if (good[i]) {return i;}}return -1;}public static boolean[] goodArray(int[] g, int[] c) {int N = g.length;int M = N << 1;int[] arr = new int[M];for (int i = 0; i < N; i++) {arr[i] = g[i] - c[i];arr[i + N] = g[i] - c[i];}for (int i = 1; i < M; i++) {arr[i] += arr[i - 1];}LinkedList<Integer> w = new LinkedList<>();for (int i = 0; i < N; i++) {while (!w.isEmpty() && arr[w.peekLast()] >= arr[i]) {w.pollLast();}w.addLast(i);}boolean[] ans = new boolean[N];for (int offset = 0, i = 0, j = N; j < M; offset = arr[i++], j++) {if (arr[w.peekFirst()] - offset >= 0) {ans[i] = true;}if (w.peekFirst() == i) {w.pollFirst();}while (!w.isEmpty() && arr[w.peekLast()] >= arr[j]) {w.pollLast();}w.addLast(j);}return ans;}}

第二种依次累加 看是否出现小于0的数

第一 组装一个原始数组的两倍长度的累加和

第二如何还原原是数组i到j的累加和 通过2被数组的j减去i就等于数组i到j的累加和

四 数组里面的数组成aim的张数最少是多少?

4.1 描述

4.2 分析

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

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

相关文章

【MySQL】库的操作【创建和操纵】

文章目录 1.创建数据库1.1字符集和校验规则1.查看系统默认字符集以及校验规则2.查看数据库支持的字符集以及校验规则 1.2校验规则对数据库的影响1.创建一个数据库&#xff0c;校验规则使用utf8_ general_ ci[不区分大小写]2.创建一个数据库&#xff0c;校验规则使用utf8_ bin[区…

flask的基本使用2

上一篇我们介绍了基本使用方法 flask使用 【 1 】基本使用 from flask import Flask# 1 实例化得到对象 app Flask(__name__)# 2 注册路由--》写视图函数 app.route(/) def index():# 3 返回给前端字符串return hello worldif __name__ __main__:# 运行app&#xff0c;默认…

idea的代码提示插件使用记录

安装ai插件卸载之后&#xff0c;偶尔还是idea一直占用100%&#xff0c;将idea缓存全清理了&#xff0c;重新生成之后就正常了 idea官方插件 下面几个感觉…基本没有感觉 按行提示的偶尔有提示&#xff0c;&#xff08;cpu占用不小&#xff0c;提示不强&#xff09; 缺点&am…

Sentinel解决雪崩问题

我们或多或少都对雪崩问题有点了解&#xff0c;在微服务系统中&#xff0c;各个微服务互相调用&#xff0c;关系错综复杂&#xff0c;如果其中一个微服务挂了或者处理消息的速度大幅下降&#xff0c;需要被处理的消息越积越多&#xff0c;那么影响的不仅仅是本微服务的功能&…

C++ | Leetcode C++题解之第199题二叉树的右视图

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> rightSideView(TreeNode* root) {unordered_map<int, int> rightmostValueAtDepth;int max_depth -1;stack<TreeNode*> nodeStack;stack<int> depthStack;nodeStack.push(ro…

SCI二区|北极海鹦优化算法(APO)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;W Wang受到北极海鹦的生存和捕食行为启发&#xff0c;提出了北极海鹦优化算法&#xff08;Arctic Puffin Optimization, APO&#xff09;。 2.算法原理 2.1算法思想 …

Tcmalloc工具定位内存泄漏问题

内存泄漏问题定位 gperftools工具安装 执行如下操作&#xff1a; git clone https://github.com/gperftools/gperftools.git 注&#xff1a;如果网速较慢&#xff0c;可直接去下载压缩包。 如我下载的地址&#xff1a;https://github.com/gperftools/gperftools/releases/ta…

SA 注册流程

目录 1. UE开机后按照3GPP TS 38.104定义的Synchronization Raster搜索特定频点 2.UE尝试检测PSS/SSS&#xff0c;取得下行时钟同步&#xff0c;并获取小区的PCI&#xff1b;如果失败则转步骤1搜索下一个频点&#xff1b;否则继续后续步骤&#xff1b; 3.解析Mib&#xff0c;…

WDG看门狗

1 WDG 1.1 简介 WDG是看门狗定时器&#xff08;Watchdog Timer&#xff09;的缩写&#xff0c;它是一种用于计算机和嵌入式系统中的定时器&#xff0c;用来检测和恢复系统故障。 看门狗就像是一个忠诚的宠物狗&#xff0c;它时刻盯着你的程序&#xff0c;确保它们正常运行。…

SpringBoot启动出错:无法访问org.springframework.boot.autoconfigure.SpringBootApplication

无法访问org.springframework.boot.autoconfigure.SpringBootApplication类文件具有错误的版本 61.0&#xff0c;应为 52.0请删除该文件或确保该文件位于正确的类路径子目录中。 出现该问题是由于版本不兼容&#xff0c; 在pom.xml文件中&#xff0c;修改版本为2开头即可

一个用于Win的自动复制文本的工具:Auto_Copy

自动复制工具 这是一个用在 Windows 上的的小工具,会将你选中的任何文本保存下来,可以通过点击右键粘贴选中内容。 一、灵感来源: 在使用Mobaxterm时,我注意到其软件中具备选中即自动复制和右键直接粘贴的功能。但是,这种选中自动复制的功能仅在软件内部有效。由于这一功…

数字图像处理之【高斯金字塔】与【拉普拉斯金字塔】

数字图像处理之【高斯金字塔】与【拉普拉斯金字塔】 1.1 什么是高斯金字塔&#xff1f; 高斯金字塔&#xff08;Gaussian Pyramid&#xff09;是一种多分辨率图像表示方法&#xff0c;用于图像处理和计算机视觉领域。它通过对原始图像进行一系列的高斯平滑和下采样操作&#x…

RTMP推流到SRS流媒体服务器消息处理

RTMP推流到SRS流媒体服务器消息处理 SRS和客户端是怎么交换消息的&#xff1f;各个消息有什么作用&#xff1f;握手成功后&#xff0c;SRS和客户端进行消息交换&#xff0c;对应wiresharek这部分截图&#xff1a; 流程图&#xff08;之前画的&#xff0c;可能不够详细&#xf…

在Linux (Ubuntu 16) 下安装LabVIEW

用户尝试在Ubuntu 16操作系统上安装LabVIEW&#xff0c;但找不到合适的安装文件来支持Ubuntu。已经下载了运行时文件&#xff0c;并尝试将.rpm包转换为.deb包并安装在Ubuntu上。然而&#xff0c;安装完成后&#xff0c;没有在应用程序中看到LabVIEW的图标。 用户希望能够在Ubu…

【操作系统】内存管理——页面分配策略(个人笔记)

学习日期&#xff1a;2024.6.28 内容摘要&#xff1a;页面分配策略和内存映射文件&#xff0c;内存映射文件 页面分配置换策略 基本概念 驻留集&#xff0c;指请求分页存储管理中给进程分配的物理块的集合&#xff0c;在采用了虚拟存储技术的系统中&#xff0c;驻留集大小一…

springcloud第4季 分布式事务seata实现AT模式案例2【经典案例】

一 seata案例 1.1 背景说明 本案例使用seata的at模式&#xff0c;模拟分布式事务场景&#xff1a;【下订单&#xff0c;减库存&#xff0c;扣余额&#xff0c;改状态】 AT模式原理&#xff1a;是2pc方案的演变&#xff0c; 一阶段&#xff1a;业务数据和回滚日志记录在同一…

Android studio 打包低版本的Android项目报错

一、报错内容 Execution failed for task :app:packageRelease. > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade> com.android.ide.common.signing.KeytoolException: Failed to read key key0 from store "…

static修饰的对象在内存中的存储及其用法

一、static修饰的变量在内存中的存储位置 static关键字无论是在C语言还是C中都有着极其重要的作用&#xff0c;那么对于static来说&#xff0c;它修饰的对象是存储在内存的哪个位置呢&#xff1f;它的作用与它在内存中的位置有什么联系&#xff1f;还有它都适用于哪些场景&…

15.数据库简介+MySQl使用+SQL语句

文章目录 数据库简述一.数据库简介DB1.定义:2.DBMS数据库管理系统3.数据库分类 二.MySQL的安装1.安装步骤2.MySQL数据库图形管理工具3.mysql程序常用命令4.MySQL字符集及字符序5.Navicat快捷键操作 三.MySQL数据库基本操作 .........................................表管理一.…

RPC远程过程调用--Thrift

RPC远程过程调用–Thrift 简介 Thrift是一个由Facebook开发的轻量级、跨语言的远程服务调用框架&#xff0c;后进入Apache开源项目。支持通过自身接口定义语言IDL定义RPC接口和数据类型&#xff0c;然后通过编译器生成不同语言代码&#xff0c;用于构建抽象易用、可互操作的R…