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

代码随想录算法训练营四十二天|单调栈part02

LeetCode 42 接雨水

题目链接:42. 接雨水 - 力扣(LeetCode)

给定 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.单调栈按行方向计算雨水容量,如图:

2.使用单调栈内元素的顺序:

从栈顶到栈底的顺序应该是从小到大的顺序。因为一旦发现添加的柱子的高度大于栈顶元素,说明出现凹槽,栈顶元素就是凹槽底部的柱子,栈顶第二个元素就是凹槽左边的柱子,新添加的柱子就是凹槽右边的柱子。

如图所示:

3.遇到相同高度的柱子怎么办,如图所示:

我们把栈顶元素先弹出,再将新元素加入栈中,因为高度相同,我们只使用最靠右边的柱子来计算即可。

根据以上分析,接下来就看单调栈的处理逻辑:

1.当前加入的元素高度小于栈顶元素的高度,直接将当前元素加入栈中即可;

2.当前加入的元素高度等于栈顶元素的高度,先将栈顶元素弹出,再将当前元素加入栈中即可;

3.当前加入的元素高度大于栈顶元素的高度:首先先将栈顶元素弹出,那么这个柱子就是凹槽的底部,它的高度记为mid;此时栈顶元素就是凹槽左边的柱子,当前加入的元素时凹槽右边的位置;所以雨水的高度应该是:凹槽两边柱子的最小高度-mid宽度是:凹槽右边的下标-凹槽左边的下标-1;所以体积就是:高度*宽度。

根据以上处理逻辑,给出代码:

class Solution {public int trap(int[] height) {int n = height.length;int res = 0;Stack<Integer> st = new Stack<>();st.push(0);for (int i = 1; i < n; i++) {if (height[i] == height[st.peek()]) {st.pop();}while (!st.isEmpty() && height[i] > height[st.peek()]) {int mid = height[st.peek()];st.pop();if (!st.isEmpty())res += (Math.min(height[i], height[st.peek()]) - mid) * (i - st.peek() - 1);}st.push(i);}return res;}
}

LeetCode 84 柱状图中最大的矩形

题目链接:84. 柱状图中最大的矩形 - 力扣(LeetCode)

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:

输入: heights = [2,4]
输出: 4

依然要明确单调栈内元素的顺序:

从栈顶到栈底的顺序应该是从大到小的顺序。因为本题是要找到每个柱子左右两边第一个小于该柱子的柱子,和接雨水正好是相反的。

除了顺序,其他的逻辑和接雨水是差不多得,这里就不再赘述了。

代码如下:

class Solution {public int largestRectangleArea(int[] heights) {int[] height=new int[heights.length+2];height[0]=0;for(int i=1;i<=heights.length;i++){height[i]=heights[i-1];}height[heights.length+1]=0;int n=height.length;int res=0;Stack<Integer> st=new Stack<>();st.push(0);for(int i=1;i<n;i++){if(height[i]==height[st.peek()])st.pop();while(!st.isEmpty()&&height[i]<height[st.peek()]){int mid=height[st.peek()];st.pop();if(!st.isEmpty()){int left=st.peek();int right=i;res=Math.max(res,mid*(right-left-1));}}st.push(i);}return res;}
}

可以看到,在heights数组首位都加了一个元素0,这是为什么?

首先,在末尾加0是为了防止数组本身就是非递减的,那么这样一直到最后都没有进行res的计算,直接返回0,所以要在末尾加一个0。

其次,在开头加0是为了防止数组本身是非递增的,那么这样对于第一个柱子,我们无法得到left,所以要在开头加一个元素0。

http://www.dtcms.com/a/327482.html

相关文章:

  • 【Activiti】要点初探
  • 迈向具身智体人工智能:LLM 和 VLM 驱动的机器人自主性和交互性
  • 11-docker单机版的容器编排工具docker-compose基本使用
  • Qt中定时器介绍和使用
  • 文字转语音 edge_tts
  • Spring IoC实现原理详解
  • [激光原理与应用-251]:理论 - 几何光学 - 长焦与短焦的比较
  • 晶片与电路板的桥梁-封装
  • 回归预测 | Matlab实现CNN-BiLSTM-self-Attention多变量回归预测
  • 外卖投诉:差评转复购的3步攻略
  • DOM2 Style的隐藏武器:getComputedStyle()的使用指南
  • idea git commit特别慢,cpu100%
  • dag实现案例 02、实现简易版dag调度系统(基于01之上升级)
  • GeoScene 空间大数据产品使用入门(6)进阶模型
  • 软考备考(三)
  • jupyter notebook中查看kernel对应环境的解决方案
  • RK3568 Linux驱动学习——Linux LED驱动开发
  • 安全合规5--终端安全检测和防御技术
  • 【1】Transformers快速入门:自然语言处理(NLP)是啥?
  • 肖臻《区块链技术与应用》第九讲:比特币交易的“智能”核心:深入解析脚本语言Script
  • 常见的设计模式(2)单例模式
  • TDengine 初体验
  • Flink Python API 提交 Socket 数据源的 WordCount 作业
  • TDengine 可观测性最佳实践
  • 荣耀手机无法连接win11电脑,错误消息:“无法在此设备上加载驱动程序 (hn_usbccgpfilter.sys)。”解决方案
  • Flink运行时的实现细节
  • 嵌入式Linux进程管理面试题大全(含详细解析)
  • 基于热成像摄像头检测蚊子的可行性研究
  • iOS 签名证书全生命周期实战,从开发到上架的多阶段应用
  • 《Qwen2.5-VL 》论文精读笔记