首页 > 其他分享 >[LeetCode Hot 100] LeetCode84. 柱状图中最大的矩形

[LeetCode Hot 100] LeetCode84. 柱状图中最大的矩形

时间:2023-12-24 15:56:47浏览次数:39  
标签:peek int LeetCode84 Hot heights 柱状图 && length stack

题目描述

思路:枚举+优化(单调栈)

先固定矩阵的高。
然后向左向右找到第一个比当前元素值小的元素,确定好左右边界。

对于元素2来说:

  • 向左找到第一个比当前元素值小的元素:1的右边界
  • 向右找到第一个比当前元素值小的元素:3的右边界

枚举每个元素的上边界,确定往左数最远到达哪个边界(即寻找左边第一个比它小的数),往右数最远到达哪个边界(即寻找右边第一个比它小的数)

思路总结:

  1. 对于一个高度,如果能得到向左和向右的边界
  2. 那么就能对每个高度求一次面积
  3. 遍历所有高度,即可得出最大面积
  4. 使用单调栈,在出栈操作时得到前后边界并计算面积

☆方法一:


class Solution {
    public int largestRectangleArea(int[] heights) {
        
        int[] left = new int[heights.length];
        Arrays.fill(left, -1);
        Deque<Integer> stack = new ArrayDeque<>();
        // 计算每根柱子左边第一个小于这根柱子的柱子
        for (int i = heights.length - 1; i >= 0; i --) {
            while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
                left[stack.peek()] = i;
                stack.pop();
            }
            stack.push(i);
        }
        // 计算每根柱子左边第一个小于这根柱子的柱子
        int[] right = new int[heights.length];
        Arrays.fill(right, heights.length);
        stack = new ArrayDeque<>();
        for (int i = 0; i < heights.length; i ++) {
            while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
                right[stack.peek()] = i;
                stack.pop();
            }
            stack.push(i);
        }

        int res = 0;
        for (int mid = 0; mid < heights.length; mid ++) {
            int height = heights[mid];
            res = Math.max(res, height * (right[mid] - left[mid] - 1));
        }
        return res;
    }
}
  • left数组:初始化为-1
  • right数组:初始化为lengths.length
  • 宽度:right[i] - left[i] - 1
  • 高度:heights[i]
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

从右开始遍历:求得左边界

for (int i = heights.length - 1; i >= 0; i --) {
	while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
		left[stack.peek()] = i;
		stack.pop();
	}
	stack.push(i);
}

从左开始遍历:求得右边界

for (int i = 0; i < heights.length; i ++) {
	while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
		right[stack.peek()] = i;
		stack.pop();
	}
	stack.push(i);
}

方法二:

class Solution {
    public int largestRectangleArea(int[] heights) {
        
        int[] left = new int[heights.length];
        Deque<Integer> stack = new ArrayDeque<>();
        // 计算每根柱子左边第一个小于这根柱子的柱子
        for (int i = 0; i < heights.length; i ++) {
            while (!stack.isEmpty() && heights[i] <= heights[stack.peek()]) {
                stack.pop();
            }
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }
        // 计算每根柱子左边第一个小于这根柱子的柱子
        int[] right = new int[heights.length];
        Arrays.fill(right, heights.length);
        stack = new ArrayDeque<>();
        for (int i = heights.length - 1; i >= 0; i --) {
            while (!stack.isEmpty() && heights[i] <= heights[stack.peek()]) {
                stack.pop();
            }
            right[i] = stack.isEmpty() ? heights.length : stack.peek();
            stack.push(i);
        }

        int res = 0;
        for (int mid = 0; mid < heights.length; mid ++) {
            int height = heights[mid];
            res = Math.max(res, height * (right[mid] - left[mid] - 1));
        }
        return res;
    }
}

从左开始遍历:求得左边界

for (int i = 0; i < heights.length; i ++) {
	while (!stack.isEmpty() && heights[i] <= heights[stack.peek()]) {
		stack.pop();
	}
	left[i] = stack.isEmpty() ? -1 : stack.peek();
	stack.push(i);
}

从右开始遍历:求得右边界

for (int i = heights.length - 1; i >= 0; i --) {
	while (!stack.isEmpty() && heights[i] <= heights[stack.peek()]) {
		stack.pop();
	}
	right[i] = stack.isEmpty() ? heights.length : stack.peek();
	stack.push(i);
}

方法三:单调栈一次遍历

结合方法一和方法二,通过一次循环搞定。
需要保证两个for循环遍历的方向一致。

标签:peek,int,LeetCode84,Hot,heights,柱状图,&&,length,stack
From: https://www.cnblogs.com/keyongkang/p/17924455.html

相关文章

  • 在Flutter中使用PhotoViewGallery指南
    介绍Flutter中的PhotoViewGallery是一个功能强大的插件,用于在应用中展示可缩放的图片。无论是构建图像浏览器、相册应用,还是需要在应用中查看大图的场景,PhotoViewGallery都是一个不错的选择。添加依赖首先,需要在pubspec.yaml文件中添加photo_view插件的依赖。打开该文件,然后在depen......
  • [LeetCode Hot 100] LeetCode74. 搜索二维矩阵
    题目描述思路:二维矩阵坐标变换+二分查找二维矩阵坐标变换:只要知道二维数组的的行数m和列数n,二维数组的坐标(i,j)可以映射成一维的index=i*n+j;反过来也可以通过一维index反解出二维坐标i=index/n,j=index%n。(n是列数)把二维数组matrix的元素访问抽象成在......
  • [LeetCode Hot 100] LeetCode153. 寻找旋转排序数组中的最小值
    题目描述思路如果数组翻转后又回到升序的情况,即nums[left]<=nums[right],则nums[left]就是最小值,直接返回。如果数组翻转,需要找到数组中第二部分的第一个元素:若nums[left]<=nums[mid],说明区间[left,mid]连续递增,则最小元素一定不在这个区间里,可以直接排除,最小值在[......
  • [LeetCode Hot 100] LeetCode33. 搜索旋转排序数组
    题目描述思路如果nums[left]<=nums[mid],则[left,mid]有序如果nums[left]>nums[mid],则[mid,right]有序方法一:classSolution{publicintsearch(int[]nums,inttarget){if(nums==null||nums.length==0)return-1;intleft=0,ri......
  • [LeetCode Hot 100] LeetCode35. 搜索插入位置
    题目描述思路基础二分搜索模板本质:找到第一个大于等于target的元素的下标注意:该题目不存在重复元素存在一种特殊情况:target>nums的最大值,此时插入的位置正好是left的位置方法一:classSolution{publicintsearchInsert(int[]nums,inttarget){if......
  • [LeetCode Hot 100] LeetCode34.在排序数组中查找元素的第一个和最后一个位置
    题目描述思路:二分查找之寻找左右侧边界两个关键点:1.数组有序;2.时间复杂度O(logn)方法一:classSolution{publicint[]searchRange(int[]nums,inttarget){if(nums.length==0||nums==null){returnnewint[]{-1,-1};}......
  • Highcharts 用SVGRenderer方法使柱状图连接列边​
    需求在Highcharts中,可以使用SVGRenderer方法来创建路径连接柱状图的列边,并根据具体的数据和需求进行适当的调整和扩展。分析要使用Highcharts的SVGRenderer方法来绘制柱状图并连接列边,可以按照以下步骤进行操作:创建柱状图:使用Highcharts的 chart 方法创建一个柱状图,并......
  • backblaze b2通过cli下载大文件快照snapshots
    按照官方的常规方式,是先在cli下查看buckets  list-buckets找到b2snapshots的名称,然后通过download-file下载b2download-file--thread1b2://snapshots目录/备份文件名.注意下载大文件,最好是把现成设置成1-----------------------以上是常规方法,但是我下载了几......
  • vue中echarts图表---正负轴柱状图
    一、安装npmiecharts--save二、引入//全局引入importechartsfrom'echarts'Vue.prototype.$echarts=echarts//局部【这里使用局部引入】importechartsfrom'echarts';三、代码1<!--容器-->2<divid="cylinderEcharts"ref="cyl......
  • 解决 Photoshop 中的“暂存盘已满”错误
    问题:“暂存盘已满”错误解决方案注意:建议在使用Photoshop时,操作系统硬盘上具有50GB的可用空间。根据您正在处理的文件类型,可能需要额外的可用空间。Ctrl+K打开首选项【暂存盘】-【D盘】优化Photoshop的使用空间禁用自动恢复存储:您可以通过禁用“自动存储恢复信息”选项(“......