单调栈练习(五)— 子数组的最小值之和

题目
同样的LeetCode原题:题目链接

给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。

由于答案可能很大,因此 返回答案模 10^9 + 7 。

在这里插入图片描述

思路

暴力解
先来说暴力解的思路:
三层for循环,找到每一个子数组中的最小值,0-0,0-1,0-2 … 0-N。1-1,1-2,1-3…1-N。并将每一个子数组的最小值相加即可,时间复杂度 O ( N 3 ) O(N^3) O(N3)

在这里插入图片描述

代码

public static int subArrayMinSum2(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int N = arr.length;int ans = 0;for (int i = 0; i < N; i++) {for (int j = i; j < N; j++) {int min = arr[i];for (int k = i + 1; k <= j; k++) {min = Math.min(min, arr[k]);}ans += min;}}return ans;}

优化的普通解

优化的方法是根据题目中给定的 arr[],生成对应的 left[] 和 right[]。

left[]:left[i] = x ,表示左侧最近 <= arr[i] 的位置在 x(x表示对应的索引)
right[]:right[i] = y,表示右侧最近 < arr[i] 的位置在y(y表示对应的索引)

生成 left[] 和 right[]的作用在于,根据当前子数组中最小值 arr[i] 在 left[]、right[]中获取左右最小且近的边界值后,直接进行计算求出以 arr[i] 作为子数组最小值的累加和,优化后的时间复杂度是 O ( N ) O(N) O(N)

来看下面的例子:当前 arr[8] = 7 ,找到左侧最近且小的值在是4位置的3,右侧最近且小的值是12位置4。
在这里插入图片描述

此时,以7作为最小值的子数组范围是 5 ~ 11,并且此范围内所有值都是 >= 7 的,但是因为要以7作为最小值,所以5 ~ 11范围内所求的子数组要把8位置的7涵盖进去。此时利用 left[8] = 4 、right[8] = 12, (8 - 4)x(12 - 8)x (arr[8]) = 112,就是7作为最小值的时候所有子数组最小值的累加和。

需要注意的是:如果是普通的无重复值数组,那么很好处理,但如果数组中有重复值,就需要额外注意!!!

举例:
在这里插入图片描述
碰上有重复值的数组,要稍微多考虑一些,就是左右边界的设定选择改怎么选?本题中答案选用的是第一种

两种选择的不同其实目的都是一个,那就是抛去重复值的计算

比如说:
此时以4位置的3作为最小值,如果依然是从1位置开始枚举每个子数组 1 - 4 、 1 - 5 … 1 - 11,那等到以7位置的3作为最小值时呢? 此时如果再从1 - 7、 1 - 8 … 1 - 11。那么和之前计算的子数组最小值就包含了重复的部分。所以要去重。

代码

构建完成后,遍历一遍 arr[] , 将每一个值都作为子数组的最小值,并根据 left[]、right[] 算出子数组的个数,个数 * 最小值,不就是我们想要的答案,再将求出来的每一个结果进行累加。

 public static int subArrayMinSum2(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int[] left = leftNearLessEqual1(arr);int[] right = rightNearLess1(arr);int ans = 0;for (int i = 0; i < arr.length; i++) {int start = i - left[i];int end = right[i] - i;ans += start * end  * arr[i];}return ans;}public static int[] rightNearLess1(int[] arr) {int N = arr.length;int[] right = new int[N];int ans;for (int i = 0; i < N; i++) {ans = N;for (int j = i + 1; j < N; j++) {if (arr[j] < arr[i]) {ans = j;break;}}right[i] = ans;}return right;}public static int[] leftNearLessEqual1(int[] arr) {int N = arr.length;int[] left = new int[N];int ans;for (int i = N - 1; i >= 0; i--) {ans = -1;for (int j = i - 1; j >= 0; j--) {if (arr[j] <= arr[i]) {ans = j;break;}}left[i] = ans;}return left;}

单调栈
单调栈其实就是将构建left[]、right[]的过程加快了,其逻辑是不变的。
这里的单调栈是自己用数组实现,没有用系统提供的Stack,但是照比系统提供的性能要更好一些。

 public static int sumSubarrayMins(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int[] stack = new int[arr.length];int[] left = leftNearLessEqual2(arr, stack);int[] right = rightNearLess2(arr, stack);long ans = 0;for (int i = 0; i < arr.length; i++) {long start = i - left[i];long end = right[i] - i;ans += (start * end) * arr[i];ans %= 1000000007;}return (int)ans;}public static int[] rightNearLess2(int[] arr,int[] stack) {int N = arr.length;int[] right = new int[N];int size = 0;for (int i = 0; i < N; i++) {while (size != 0 && arr[i] < arr[stack[size - 1]]){right[stack[--size]] = i;}stack[size++] = i;}while (size != 0){right[stack[--size]] = N;}return right;}public static int[] leftNearLessEqual2(int[] arr,int[] stack) {int N = arr.length;int[] left = new int[N];int size = 0;for (int i = N - 1; i >= 0; i--) {//stack[size - 1] :当前最后加入到数组中元素即为栈顶元素//stack[--size] :出栈操作,弹出栈顶元素并且大小 - 1,后加入的元素要覆盖当前位置while (size != 0 && arr[i] <= arr[stack[size - 1]]){//当前 i 位置 使栈顶元素出栈,所以 left[栈顶元素左侧小且近] = 当前下标 ileft[stack[--size]] = i;}//入栈操作:存储当前元素索引stack[size++] = i;}while (size != 0){left[stack[--size]] = -1;}return left;}

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

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

相关文章

OpenssH 漏洞修复

文章目录 OpenSSH 漏洞修复需求&#xff1a;准备环境配置阿里云yum源关闭防火墙 && SELinux安装 telnet-server安装 zlib 软件包安装OpenssL安装 OpenssH报错信息 OpenSSH 漏洞修复 场景&#xff1a; CentOS Stream 9 系统ssh默认版本一般是OpenSSH_8.7p1 &#xff0c;…

【国内访问github不稳定】可以尝试fastgithub解决这个问题

1、下载 https://github.com/dotnetcore/FastGithub https://github.com/dotnetcore/FastGithub/releases 官网下载即可&#xff0c;比如&#xff0c;我用的是这个&#xff1a;fastgithub_osx-x64.zip&#xff08;点这里下载&#xff09; 2、安装 如下图双击启动即可 3、…

科研绘图(二)气泡图

气泡矩阵图&#xff08;Bubble Matrix Plot&#xff09;&#xff0c;通常用于显示三个变量之间的关系。这种图表类型将数据点表示为气泡的形式&#xff0c;其中气泡的大小通常表示第三个数值变量的大小。图表的X轴和Y轴代表两个分类或定量变量。颜色可能代表另一个分类变量或是…

CAN总线通信详解 (超详细配34张高清图)

CAN总线通信详解 (超详细配34张高清图) 1. CAN总线历史 CAN 是 Controller Area Network 的缩写&#xff08;以下称为 CAN&#xff09;&#xff0c;是 ISO国际标准化的串行通信协议。 在当前的汽车产业中&#xff0c;出于对安全性、舒适性、方便性、低公害、低成本的要求&#…

Python爬虫---scrapy shell 调试

Scrapy shell是Scrapy提供的一个交互式shell工具&#xff0c;它可以帮助我们进行爬虫的开发和调试。可以使用它来测试xpath或css表达式&#xff0c;查看它们是如何工作的&#xff0c;以及它们从你试图抓取的网页中提取的数据。它允许你在编写spider时交互地测试表达式&#xff…

图像异或加密及唯密文攻击

异或加密 第一种加密方式为异或加密&#xff0c;异或加密的原理是利用异或的可逆性质&#xff0c;原始图像的像素八位bit分别与伪随机二进制序列异或&#xff0c;得到的图像就为加密图像。如下图对lena图像进行加密。 伪随机序列为一系列二进制代码&#xff0c;它受加密秘钥控…

CSS样式学习

html超文本传输标签&#xff0c;属性等权重 outline 标签轮廓 <input type"text"> <textarea cols"30" rows"10"></textarea> outline: none; 表示无轮廓 &#xff08;开发时用的比较多&#xff09; CSS 轮廓&#xff…

数据结构入门到入土——栈(Stack)和队列(Queue)

目录 一&#xff0c;栈&#xff08;Stack&#xff09; 1.1 概念 1.2 栈的使用 1.3 栈的模拟实现 1.4 栈的应用场景 1.5 栈&#xff0c;虚拟机栈&#xff0c;栈帧有什么区别&#xff1f; 二&#xff0c;队列&#xff08;Queue&#xff09; 2.1 概念 2.2 队列的使用 2.3 …

前端js调用Lodop实现云打印

一、下载Lodop控件 官网&#xff1a;下载中心 - Lodop和C-Lodop官网主站 二、解压后安装 双击进行安装&#xff0c;里面有些页面文件是一些教程案例 勾选云服务工作模式 安装成功会自动启动 浏览器访问地址&#xff1a;http://localhost:8000/ 首页最下面有个教程案例跳转地址&…

DNS 域名解析

一 、名字解析介绍和DNS 当前TCP/IP网络中的设备之间进行通信&#xff0c;是利用和依赖于IP地址实现的。但数字形式的IP地址是很难记忆的。当网络设备众多&#xff0c;想要记住每个设备的IP地址&#xff0c;可以说是"不可能完成的任务"。那么如何解决这一难题呢&…

蓝桥杯单片机进阶教程4——需要分配进程的模块

前言&#xff1a; 【蓝桥杯单片机保姆级教学】 https://www.bilibili.com/video/BV1h3411m7Aw/?p117&share_sourcecopy_web&vd_sourcec4fc67867c5218768e783d04475bc5a2 P117-118 比赛的时候也按照这个顺序来写 一、数码管显示 分析考题 &#xff08;1&#xff09;…

javascript_forEach中使用异步函数执行顺序问题,错误原因+解决思路

javascript_forEach中使用异步函数执行顺序问题&#xff0c;错误原因解决思路 start 最近在写异步逻辑的时候&#xff0c;经常会使用 async/await。有些时候需要执行异步逻辑的函数比较多&#xff0c;就习惯用 forEachasync/await 去处理函数了。在测试的过程中会发现&#x…

Unity之角色控制器

PS:公司终于给我派任务了&#xff0c;最近几天都没学Unity&#x1f927;。 一、角色控制器的实现方式 目前小编知道的角色控制器实现方式有三种&#xff1a; 应用商店的角色控制系统Unity自己的角色控制器通过物理系统去做角色控制器 本篇介绍的是第二种Unity自己的角色控制…

数字化时代,VR全景展示如何让用户一窥全貌?

数字化时代&#xff0c;VR全景展示为各行各业提供了无限的可能性。随着VR全景技术的逐步普及&#xff0c;VR全景展示以其独特的呈现方式和新颖十足的交互体验&#xff0c;正在不断改变着人们对于展示宣传的理解。 传统的展示方式&#xff0c;通常需要将产品、图文、品牌等元素集…

滴水内存地址堆栈

两个十六进制数 刚好是一个字节刚好 DC这的一个字节数据为E4 一个内存地址 后面表示四个字节的数据 所以有八个十六进制的数 BASE是高地址 所以放入一个四字节后就 -4

RK3568驱动指南|第十二篇 GPIO子系统-第136章 实战:实现动态切换引脚复用功能

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

sectigo ip证书种类买一年送一月

Sectigo旗下的IP证书是专为只有公网IP地址的网站准备的。Sectigo旗下的数字证书大多是域名证书&#xff0c;例如&#xff0c;单域名SSL证书、多域名SSL证书、通配符SSL证书等。这些证书申请时必须验证域名所有权&#xff0c;申请者需要有一个拥有管理全的域名网站&#xff0c;那…

SRM供应商招标采购管理系统(源码)

软件相关资料获取&#xff1a;点我获取 一、SRM供应商在线采购 SRM供应商在线采购是指企业通过互联网平台&#xff0c;实现对供应商的在线招募、选择、关系管理等一系列活动。这种采购方式具有高效、透明、便于管理的特点&#xff0c;能够帮助企业降低采购成本&#xff0c;提…

陶瓷碗口缺口检测-图像形态学

图像形态学 对得到的灰度图像&#xff0c;需要进行二值化处理和区域填充。二值化涉及两个步骤&#xff0c;第一&#xff0c;对图像行图像分割&#xff0c;将图像分割成目标和和背景&#xff1b;第二&#xff0c;对分割后图像进行区域填充。本例中的背景为黑色&#xff0c;可以…

全自动网页生成系统网站源码重构版

源码优点: 所有模板经过精心审核与修改&#xff0c;完美兼容小屏手机大屏手机&#xff0c;以及各种平板端、电脑端和360浏览器、谷歌浏览器、火狐浏览器等等各大浏览器显示。 免费制作 为用户使用方便考虑&#xff0c;全自动网页制作系统无需繁琐的注册与登入&#xff0c;直…