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

news2024/12/27 12:17:21

一 滑动窗口设计知识点

滑动窗口是什么?

滑动窗口是一种想象出来的数据结构: 滑动窗口有左边界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 test
	public 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 test
	public 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.coloradmin.cn/o/1893442.html

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

相关文章

【免费可视化工具】助力风电行业智能化管理

在绿色能源日益成为全球共识的今天&#xff0c;风电作为清洁能源的重要组成部分&#xff0c;正以前所未有的速度发展。然而&#xff0c;随着风电场规模的扩大和数量的增加&#xff0c;如何高效、直观地管理和监控风电资源成为了一个亟待解决的问题。 而山海鲸可视化这款免费可…

使用微信开发者工具连接gitee

编写代码 打开微信开发者工具 编写小程序代码 提交代码 在微信开发者工具提交代码到gitee仓库的步骤&#xff1a; 1.在gitee创建仓库&#xff0c;得到仓库url 2.微信开发者工具设置远程仓库 点击版本管理-->点击设置-->网络和认证-->认证方式选择 使用用户名和…

Windows系统安装分布式搜索和分析引擎Elasticsearch与远程访问详细教程

文章目录 前言系统环境1. Windows 安装Elasticsearch2. 本地访问Elasticsearch3. Windows 安装 Cpolar4. 创建Elasticsearch公网访问地址5. 远程访问Elasticsearch6. 设置固定二级子域名 前言 本文主要介绍如何在Windows系统安装分布式搜索和分析引擎Elasticsearch&#xff0c…

怎么录制电脑内部声音?好用的录音软件分享,看这篇就够了!

如何录制电脑内部声音&#xff1f;平时使用电脑工作&#xff0c;难免会遇到需要录音的情况。好用的录音软件有很多&#xff0c;也有部分录屏工具也支持录音功能。 那么如何录制电脑内部声音呢&#xff1f;本文整理了几个录制电脑内部声音的方法&#xff0c;如果你需要在电脑上录…

全网都在疯传的最新蓝海风口项目!

最近全网都在疯传这种视频&#xff0c;想必兄弟们都见到过了&#xff01; 大家看这个号&#xff0c;1天的时间&#xff0c;2个作品&#xff0c;第2个直接就爆了&#xff0c;昨天看点赞还是3.8w&#xff0c;今天已经10w了&#xff0c;这是妥妥的风口啊&#xff01; 大家有没有想…

Qt 进程间通信(一)——QSharedMemory共享内存

QSharedMemory共享内存 序言环境理论—逻辑理解实战—代码读取示例写入示例 序言 讲讲Qt的共享内存吧&#xff0c;巩固下 环境 msvc2022 Qt5.15 参考文档&#xff1a;https://doc.qt.io/qt-5/qsharedmemory.html 理论—逻辑理解 看下面前&#xff0c;你需要将共享内存看成…

数字研发·驱动变革 | 2024达索系统装备行业数字化研发专题研讨会成功举办

2024年6月28日&#xff0c;由百世慧举办的“数字研发驱动变革|2024达索系统装备行业数字化研发专题研讨会”在达索系统&#xff08;重庆&#xff09;智能制造创新中心成功举办。 随着全球制造业向着智能化、数字化转型&#xff0c;我国工业装备行业也面临着转型升级的压力和机遇…

【代码随想录】【算法训练营】【第57天】 [卡码99]岛屿数量 [卡码100]岛屿的最大面积

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 卡码网。 day 57&#xff0c;周三&#xff0c;再ding一下~ 题目详情 [卡码99] 岛屿数量 题目描述 卡码99 岛屿数量 LeetCode类似题目200 岛屿数量 解题思路 前提&#xff1a; 思路&#xff1a; 重点&#…

集团型企业组织架构复杂,业务线多,如何进行高效费用管控?

企业管理中流行这样一句话&#xff1a;“企业转型&#xff0c;财务先行”。对集团型企业而言&#xff0c;当今的发展形势下&#xff0c;通过财务战略全面转型、最终撬动企业价值提升&#xff0c;是一件难而正确的事情。 集团企业具有经营规模大、产业链多、分支机构多、地域跨度…

亚马逊SC账号升级VC账号的新浪潮已然席卷整个电商界!

当前电商市场竞争激烈&#xff0c;亚马逊卖家追求业务增长。现有Amazon SC账号卖家有机会升级为VC账号&#xff0c;提供重要机遇。 SC账号是亚马逊常见卖家类型&#xff0c;为众多个人和企业提供销售平台。而VC账号则代表与亚马逊更紧密的合作关系&#xff0c;享有更多优惠、广…

phpexcel导入导出

前言&#xff1a; 如果你到处的excel软件打开有问题&#xff0c;下面有介绍解决办法 导入 1. composer init 初始化 2. 下载phpspreadsheet 这里需要注意php版本&#xff0c;需要大于7.2 composer require phpoffice/phpspreadsheet3. 编写代码 <?php require vendo…

amis中条件组合器condition-builder的使用 和 解析

1.amis中配置一个条件组合器&#xff0c;condition-builder。并根据自己业务需求配置source。这里用了一些自定义filter来进行预处理。 {"type": "condition-builder","label": "条件组合","name": "node.conditions&q…

【软件测试】Postman接口测试基本操作

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 Postman-获取验证码 需求&#xff1a;使用Postman访问验证码接口&#xff0c;并查看响应结果…

Python基于PyQt5和卷积神经网络分类模型(CNN分类算法)实现时装类别识别系统GUI界面项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 随着深度学习技术的发展&#xff0c;计算机视觉领域取得了显著的进步&#xff0c;特别是在图像分类、目…

QT截屏,截取控件为图片,指定范围截屏三种截屏方式

项目中我们常用到截取屏幕&#xff0c;Qt给我的们多种方式&#xff1a; 主要有以下三种&#xff1a; 截取全屏&#xff1b;截取控件为图片&#xff1b;指定位置截屏三种截屏方式&#xff1b; 1.截取全屏 常用&#xff1a; 实现&#xff1a; QScreen *screen QGuiApplicat…

使用selenium定位input标签下的下拉框

先来看一下页面效果&#xff1a;是一个可输入的下拉列表 再来看一下下拉框的实现方式&#xff1a; 是用<ul>和<li>方式来实现的下拉框&#xff0c;不是select类型的&#xff0c;所以不能用传统的select定位方法。 在着手定位元素前一定一定要先弄清楚下拉列表…

汽车信息安全--数据安全:图像脱敏

General 随着车联网的发展&#xff0c;汽车越来越智能化&#xff0c;就像是一部“装着四个轮子的手机”。 有人说&#xff0c;智能手机就如同一部窃听器&#xff0c;无论你开机或者关机&#xff0c;它都会无时不刻地监听着用户的一举一动。 可想而知&#xff0c;智能车辆上…

热网无线监测系统 SystemManager.asmx SQL注入漏洞复现

0x01 产品简介 热网无线监测系统是一种先进的热力管网监测解决方案,它通过无线通信技术实现对热力管网各项参数的实时监测和数据分析,以提高供热效率、降低能耗、保障管网安全。系统利用先进的传感器技术和无线通信技术,对热力管网中的温度、压力、流量等关键参数进行实时监…

内容评分越高,谷歌排名就越靠前吗?

我研究并分析了目前流行的四个内容优化工具的内容评分和Google排名之间的关联性&#xff1a;Clearscope、 Surfer、 MarketMuse 和 Frase&#xff0c;结果显示关联性普遍不高。 虽然相关性并不一定意味着绝对的因果关系&#xff0c;但也表明&#xff0c;一味的追求内容得分并不…