首页 > 其他分享 >LeetCode84(柱状图中最大的矩形)理解单调栈

LeetCode84(柱状图中最大的矩形)理解单调栈

时间:2024-08-23 22:22:27浏览次数:7  
标签:第一个 int 基准 LeetCode84 柱状图 数组 矩形 我们

1. LeetCode84(柱状图中最大的矩形)

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= heights.length <=10^5
  • 0 <= heights[i] <= 10^4

如题意描述,要取最大的矩形面积,那么得找到宽度与高度相乘的最大值.

但我们先思考几个情形,在这张图上什么样能构成矩形

  • 长和宽都得规则,也就是只能是水平扩展,不能是不规则的扩展.
  • 对于每一个柱形,他自己本身也是一个矩形.

基于以上的描述,接下来我们就得找到构成矩形的长宽,从何处取.

对于每一个柱形,我们得先选取一个基准.什么叫基准呢,就是以这个柱子的高度,去找寻能够凑成与这个柱子构成的矩形.

可能还是很模糊,我们举具体的例子来说明:

  • 例如我们来查看索引1处这个柱子

以他为基准,我们想要尽可能的扩展这个矩形,那么说明什么?我们需要找到左边第一个比他小的柱子高度与右边比他小的第一个柱子的高度.

为什么呢,为什么水平扩展就得去要找到比他小的值呢?

因为第一个比他小的说明,只能扩展在这个索引处,不能再往左或者右方向扩展.

如果没找到呢,说明能够完全扩展到左右两端,例如此时的1.左右两端都没有出现比他小的高度,所以以他为基准.所构成的矩形面积大小为 1 * 6 = 6.

所以关键点出来了,我们得找到在左边第一个比此时柱子小的高度,与第一个右边比此时柱子小的高度.

所以我们此时才会想到单调栈,单调栈的使用场景就有我们需要找到第一个比他小或者大的数.

那问题来了,栈里面是调递增呢,还是递减呢

注意:

  • 要找第一个比他小的,栈里面递减
  • 要找第一个比他大的,栈里面递增

所以我们的栈里面是单调递减的.这样我们再来解释一下,如何从这样一个单调栈中找到第一个比此时柱子高度小的值.

  • 对于柱子右边来讲,我们很好理解,遇见比此时栈顶元素(这个栈顶元素也就是我们之前提到的基准)小的数时,说明此时遇到基准第一个小的值(从左往右遍历的,遇见一个比他小的肯定就是第一个比他小的)
  • 而对于右边的第一个最小值呢?实际上就是基准从栈弹出后的下一个栈顶元素,别忘了栈里面是单调递减的,所以弹出当前栈顶元素,下一个栈顶一定是小于等于上一个的栈顶元素.

这样我们就能找到左边第一个与右边第一个比他小的值,那怎么计算这样的宽度呢?

我们观察一下 5 6 2这一段柱子

对于我们这样的算法思想,当遍历到2时,此时他是小于栈顶元素6的.所以我们要触发计算过程.

宽度如何确认呢?注意我们单调栈中存的应该是数组中的下标,我们再通过下标找到数组具体的值,相当于做了一个映射.

所以依照我们的思想

基准: mid = stack.pop()          //此时应该是3(下标,对应就是数组中的6)

第一个左边比他小的值: left = stack.peek()     //是2(下标,对应就是数组中的5)

第一个右边比他小的值: right = i       //就是此时遍历到数组的下标(对应数组中的2)

这样一看,对于此时基准6而言,左右都不能扩展,此时算出的矩形面积应该就是他自己本身构成的矩形

面积为: height[mid] * (right - left - 1) 

这样我们就得到了面积的计算公式.

此时我们考虑情况完了吗?

并没有,假设此时有这样一个数组: [1,3,6,7,9]

我们会发现数组本身就是单调的,这样按照我们之前的思路,会导致全部存入栈中,而没有产生计算.那我们如何去触发计算呢?

实际上我们在尾部填上一个0就可以啦,因为0肯定是小于数组中的元素(题目说了值大于等于0),这样就会触发我们的计算过程.

那这样就万无一失了吗?还不够,我们再试想一个数组:[9,7,6,3,1]

对于这样一个数组,在遇见7时,我们会把9弹出,但再去找栈顶元素时,栈中已经没有了值,所以我们获取不到,导致算法过程不能正常执行.所以此时我们还需要来往数组前添加一个0,来确保我们的计算逻辑的一致性.

所以整体代码为:

class Solution {
    public int largestRectangleArea(int[] heights) {
        LinkedList<Integer> stack = new LinkedList();
        int max = 0;
        //后补0为了能够触发计算的操作,前补0为了整个计算逻辑
        int[] height = new int[heights.length + 2];
        for(int i = 1,j = 0;i < height.length - 1;j++,i++){
            height[i] = heights[j];
        }
        for(int i = 0;i < height.length;i++){
            while(!stack.isEmpty() && height[stack.peek()] > height[i]){
                //mid代表基准
                int mid = stack.pop();
                //left代表左边第一个比基准小的索引值,也就是以当前基准能够扩展到左边的哪个位置
                int left = stack.peek();
                //right代表右边第一个比基准小的索引值,也就是以当前基准能够扩展到右边的哪个位置
                int right = i;
                max = Math.max(max,height[mid] * (right - left - 1));
            }
            stack.push(i);
        }
        return max;
    }
}

标签:第一个,int,基准,LeetCode84,柱状图,数组,矩形,我们
From: https://blog.csdn.net/m0_65013257/article/details/141473903

相关文章

  • echarts 3D 柱状图
    今天开发一个驾驶舱大屏,里面有柱状图的图表,而且是3D的,搜索可视化社区,有找到一个示例【https://www.makeapie.cn/echarts_content/xH0E6KFMcG.html】,纵向的柱子,但我开发的大屏,柱状图有横向、纵向两种,所以在此记录一下,便于下一次开发。注意:示例中是直接把echarts挂在了window上,作为......
  • 代码随想录算法训练营第 49 天 |LeetCode42 接雨水 LeetCode84 柱状图中最大面积矩形
    代码随想录算法训练营Day49代码随想录算法训练营第49天|LeetCode42接雨水LeetCode84柱状图中最大面积矩形目录代码随想录算法训练营前言LeetCode42接雨水LeetCode84柱状图中最大面积矩形一、LeetCode42接雨水1.题目链接2.思路3.题解二、LeetCode84柱状......
  • R绘图(06)——带errorbar的柱状图
      每次找R绘图美化都很麻烦,索性自己写个笔记慢慢补充绘图美化的指令###生成数据####设置种子以获得可重复的结果set.seed(222)#生成字符序列"AAAABBBB"char_sequence<-c("A","A","A","A","B","B","B","B")#......
  • 柱状图倒圆角4.9版本
     series处理conststackInfo={};for(leti=0;i<series[0].data.length;++i){for(letj=0;j<series.length;++j){conststackName=series[j].stack;if(!stackName){continue;}......
  • 一个专门用于Java服务端图片合成的工具,支持图片、文本、矩形等多种素材的合成,功能丰富
    前言在数字化营销的当下,企业对于图片处理的需求日益增长。然而,传统的图片处理方式往往需要复杂的操作和专业的技术,这不仅增加了工作量,也提高了时间成本。为了处理这一问题,一款能够简化图片合成流程的软件应运而生。介绍ImageCombiner是一款面向Java服务端的图片合成工具,以......
  • OpenCV图像处理——按最小外接矩形剪切图像
    引言在图像处理过程中,提取感兴趣区域(ROI)并在其上进行处理后,往往需要将处理后的结果映射回原图像。这一步通常涉及以下几个步骤:找到最小外接矩形:使用cv::boundingRect或cv::minAreaRect提取感兴趣区域的最小外接矩形。从原图中提取ROI:根据矩形坐标从原图中剪切出RO......
  • C语言-写一个用矩形法求定积分的通用函数,分别求积分区间为[0,1]sinx,cosx,e的x方的定积
    一、题目要求:二、思路①数学方面:矩形法求定积分的公式将积分图形划分成为指定数量的矩形,求取各个矩形的面积,然后最终进行累加得到结果1.积分区间:[num1,num2]2.分割数量:count每个矩形的边长:dx=(num2-num1)/count3.被积分函数:f(x)(f-对应不同的被积分函数sin......
  • 打卡信奥刷题(568)用Scratch图形化工具信奥B2082[普及组/提高] B2083 画矩形
    画矩形题目描述根据输入的四个参数:a,b,c,f......
  • canvas实现手动绘制矩形
    开场白虽然在实际的开发中我们很少去绘制流程图就算需要,我们也会通过第3方插件去实现下面我们来简单实现流程图中很小的一部分手动绘制矩形绘制一个矩形的思路我们这里绘制矩形会使用到canvas.strokeRect(x,y,w,h)方法绘制一个描边矩形x:矩形起点的x轴坐标。y:矩形起......
  • 代码随想录算法刷题训练营day49:LeetCode(42)接雨水、LeetCode(84)柱状图中最大的矩形
    代码随想录算法刷题训练营day49:LeetCode(42)接雨水、LeetCode(84)柱状图中最大的矩形LeetCode(42)接雨水题目代码importjava.util.Stack;classSolution{publicinttrap(int[]height){//用单调栈进行操作intsum=0;Stack<Integ......