503.下一个更大元素II 42.接雨水

503.下一个更大元素II 42.接雨水

503.下一个更大元素II

力扣题目链接(opens new window)

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例 1:

  • 输入: [1,2,1]
  • 输出: [2,-1,2]
  • 解释: 第一个 1 的下一个更大的数是 2;数字 2 找不到下一个更大的数;第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

提示:

  • 1 <= nums.length <= 10^4
  • -10^9 <= nums[i] <= 10^9

思路

思路:单调栈
将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了。
时间复杂度:O(n)
空间复杂度:O(n)

代码如下

public int[] nextGreaterElements(int[] nums) {if (nums == null)// 边缘条件判断return null;int[] doubleNums = new int[2 * nums.length];// 拼接两个Nums数组for (int i = 0; i < doubleNums.length; i++) {if (i < nums.length) {doubleNums[i] = nums[i];} else {doubleNums[i] = nums[i - nums.length];}}int[] result = new int[nums.length];// nums的结果集int[] doubleResult = new int[doubleNums.length];// doubleNums的结果集for (int i = 0; i < doubleNums.length; i++)doubleResult[i] = -1;Stack<Integer> stack = new Stack<>();stack.push(0);for (int i = 1; i < doubleNums.length; i++) {// 填充doubleResult数组Integer top = stack.peek();while (doubleNums[i] > doubleNums[top]) {top = stack.pop();doubleResult[top] = doubleNums[i];if (stack.isEmpty())break;top = stack.peek();}stack.push(i);}for (int i = 0; i < nums.length; i++) {// doubleResult前一半元素存储在result中result[i] = doubleResult[i];}return result;
}

优化

不扩充nums数组,在遍历的过程中模拟走了两遍nums数组
在写下面代码时,有个问题。在遍历的过程中模拟走了两遍nums数组,为什么result不定义成二倍nums长度呢?
可以看下这两行代码。result的下标来自栈顶弹出元素,这毫无疑问。之前做过的几个单调栈题目也都是这么操作的

top = stack.pop();
result[top] = nums[i % nums.length];

加入栈的元素代码如下。可以看出,加入栈的元素范围被限制在0~nums.length-1之间,所以result的大小定义为nums长度即可

stack.push(i % nums.length);

代码如下

public int[] nextGreaterElements(int[] nums) {if (nums == null)// 边缘条件判断return null;int[] result = new int[nums.length];// nums的结果集for (int i = 0; i < nums.length; i++)result[i] = -1;Stack<Integer> stack = new Stack<>();stack.push(0);for (int i = 1; i < 2 * nums.length; i++) {// 填充doubleResult数组Integer top = stack.peek();while (nums[i % nums.length] > nums[top]) {top = stack.pop();result[top] = nums[i % nums.length];if (stack.isEmpty())break;top = stack.peek();}stack.push(i % nums.length);}return result;
}

42.接雨水

力扣题目链接(opens new window)

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

在这里插入图片描述

  • 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
  • 输出:6
  • 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

示例 2:

  • 输入:height = [4,2,0,3,2,5]
  • 输出:9

思路:暴力算法

暴力算法(双指针)
求雨水的体积首先明确按照行来计算还是按照列来计算
暴力算法倾向于按照列来计算。那么以列为单位,每一列的宽度一定是1,只要求出雨水高度即可
如图
在这里插入图片描述

列中雨水的高度取决于左侧最高的列,右侧最高的列中,较小值的高度
为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍
那么此时雨水的体积等于(雨水高度 - 列高度) * 列宽 = (雨水高度 - 列高度)
时间复杂度为O(n^2)
空间复杂度为O(1)

代码如下

public static int trap(int[] height) {if (height == null)// 边缘条件判断return 0;int rainNum = 0;for (int i = 1; i < height.length - 1; i++) {int leftHeight = 0;int rightHeight = 0;for (int j = 0; j < i; j++) {// 求左侧最高列if (height[j] > leftHeight)leftHeight = height[j];}for (int j = i + 1; j < height.length; j++) {// 求右侧最高列if (height[j] > rightHeight)rightHeight = height[j];}// 求当前列的雨水体积if (Math.min(leftHeight, rightHeight) - height[i] > 0)rainNum = rainNum + Math.min(leftHeight, rightHeight) - height[i];}return rainNum;
}

优化:双指针算法

优化(双指针算法)
为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍
这样导致时间复杂度为O(n^2)
我们把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),这样就避免了重复计算。
对于当前位置而言,左边的最高高度是前一个位置的左边最高高度和本高度的最大值。
即从左向右遍历:maxLeft[i] = max(height[i], maxLeft[i - 1]);
从右向左遍历:maxRight[i] = max(height[i], maxRight[i + 1]);
时间复杂度为O(n)
空间复杂度为O(n)

代码如下

if (height == null)// 边缘条件判断return 0;int[] maxLeft = new int[height.length];// 保存当前下标i,height[i]左侧最大元素
maxLeft[0] = height[0];
for (int i = 1; i < height.length; i++) {maxLeft[i] = Math.max(height[i], maxLeft[i - 1]);
}int[] maxRight = new int[height.length];// 保存当前下标i,height[i]右侧最大元素
maxRight[height.length - 1] = height[height.length - 1];
for (int i = height.length - 2; i >= 0; i--) {maxRight[i] = Math.max(height[i], maxRight[i + 1]);
}int rainNum = 0;
for (int i = 1; i < height.length - 1; i++) {if (Math.min(maxLeft[i], maxRight[i]) - height[i] > 0) {rainNum = rainNum + Math.min(maxLeft[i], maxRight[i]) - height[i];}}
return rainNum;

思路:单调栈

思路:单调栈
单调栈题目适用于寻找一维数组中,任一个元素的右边或者左边第一个比自己大或者小的元素的位置
本题目需要寻找一个元素,左侧和右侧最大元素来计算雨水面积
使用单调栈有几个点需要搞清楚
1.单调栈是按照行方向来计算雨水,如图

在这里插入图片描述

2.使用单调栈内元素的顺序
从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。
因为一旦弹出元素,弹出元素下标mid对应的height[mid]就是凹槽的高度
此时栈顶的元素为凹槽左侧边界下标
而要入栈的元素为凹槽右侧边界下标

如图

在这里插入图片描述

3.遇到相同高度的柱子怎么办。
一旦遇到相同高度的柱子,将其弹出,需要使用最右边的柱子来计算宽度

如图

在这里插入图片描述

代码如下

// 时间复杂度为O(n)
// 空间复杂度为O(n)
public static int trap(int[] height) {if (height == null)// 边缘条件判断return 0;int rainNum = 0;Stack<Integer> stack = new Stack<>();stack.push(0);for (int i = 1; i < height.length; i++) {Integer top = stack.peek();if (height[i] >= height[top]) {Integer mid = 0;// 取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid]while (height[i] > height[top]) {mid = stack.pop();if (stack.isEmpty())break;top = stack.peek();rainNum = rainNum + (Math.min(height[top], height[i]) - height[mid]) * (i - top - 1);}}stack.push(i);}return rainNum;
}

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

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

相关文章

Linux操作系统——理解文件系统

预备知识 到目前为止&#xff0c;我们所学习到的关于文件的操作&#xff0c;全部都是基于文件被打开&#xff0c;被访问&#xff0c;访问期间比较重要的有重定向&#xff0c;缓冲区&#xff0c;一切皆文件&#xff0c;当我们访问完毕的时候需要将文件关闭&#xff0c;关闭时那…

基于FPGA的矩阵键盘驱动

按键数量较多时&#xff0c;为了减少 I/O ⼝的占⽤&#xff0c;通常将按键排列成矩阵形式。在矩阵式键盘中&#xff0c;每条⽔平线和垂直线在交叉处不直接连通&#xff0c;⽽是通过一个按键连接。⼋根线就可以控制4*416个按键&#xff0c;⽐之直接将端⼝线⽤于键盘多出了⼀倍&a…

应用层—HTTP详解(抓包工具、报文格式、构造http等……)

文章目录 HTTP1. 抓包工具的使用1.1 配置信息1.2 观察数据 2. 分析 https 抓包结果3. HTTP请求详解3.1 认识 URL3.1.1 URL 基本格式3.1.2 查询字符串 (query string)3.1.3 关于 URL Encode 3.2 认识 http 方法3.2.1 [经典问题] Get 和 Post 主要的区别是什么&#xff1f;&#…

HubSpot整合小红书,MessageBox助力多系统融合

在当今数字化潮流中&#xff0c;HubSpot与小红书的强大联盟成为了数字化市场的亮点。今天运营坛将深入解析它们的合作策略&#xff0c;聚焦于MessageBox在整合中的关键角色&#xff0c;以及它在推动HubSpot和小红书整合方面的关键作用。 HubSpot与小红书&#xff1a;数字化市场…

数据库设计和数据库对象

目录 序言 一、数据库设计的步骤 二、如何绘制E-R图 2.1 酒店管理系统的基本功能 2.2 绘制E-R 实体关系图&#xff08;三要素&#xff09;&#xff1a; 2.3 关系型数据库常见映射基数&#xff1a; 2.4 转化E-R图形成数据库模型图 三、使用三大范式实现数据库设计规范化…

本地部署轻量级web开发框架Flask并实现无公网ip远程访问开发界面

文章目录 1. 安装部署Flask2. 安装Cpolar内网穿透3. 配置Flask的web界面公网访问地址4. 公网远程访问Flask的web界面 本篇文章主要讲解如何在本地安装Flask&#xff0c;以及如何将其web界面发布到公网进行远程访问。 Flask是目前十分流行的web框架&#xff0c;采用Python编程语…

C++入门学习(七)整型

整型就是整数类型的数据&#xff08;-1&#xff0c;0&#xff0c;1等等&#xff09; 数据类型占用空间取值范围short(短整型)2字节 (-2^15 ~ 2^15-1) 32768~32767 int(整型)4字节(-2^31 ~ 2^31-1)long(长整形) Windows为4字节, Linux为4字节(32位), 8字节(64位) (-2^31 ~ 2^31…

flink部署模式介绍

在一些应用场景中&#xff0c;对于集群资源分配和占用的方式&#xff0c;可能会有特定的需求。Flink 为各种场景提供了不同的部署模式&#xff0c;主要有以下三种&#xff0c;它们的区别主要在于&#xff1a; 集群的生命周期以及资源的分配方式&#xff1b;应用的 main 方法到…

jmeter生成html性能结果报告

从3.0版本开始&#xff0c;jmeter引入了Dashboard Report模块&#xff0c;用于生成HTML类型的可视化图形报告。 1.生成html报告 1.1操作步骤&#xff1a; 进入JMeter的bin目录下&#xff1b;打开命令行窗口&#xff0c;输入以下命令&#xff1a; 对于Windows系统&#xff1a;…

open3d点云平移

功能简介 open3d中点云的平移函数为&#xff1a;pcd.translate((tx, ty, tz), relativeTrue)。当relative为True时&#xff0c;&#xff08;tx, ty, tz&#xff09;表示点云平移的相对尺度&#xff0c;也就是平移了多少距离。当relative为False时&#xff0c;&#xff08;tx, …

HCIA——20应用层:C/S、P2P、peer

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

AI绘画Midjourney绘画提示词Prompt入门到精通【宝藏级收藏】

一、AI绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支…