Leecode热题100-84.柱状图中的最大矩形

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

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

示例 1:

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

示例 2:

复制代码
输入: heights = [2,4]
输出: 4

提示:

  • 1 <= heights.length <=105
  • 0 <= heights[i] <= 104

思路都在代码注释里,自己看,看不懂的留言或者私信,看到第一时间解答

java 复制代码
class Solution {
    /**这个题第一感觉是用的单调栈的解法,这个最大的矩形必定以某一个柱子的高度为最低高度
    我们对于每个柱子,求出它左边第一个比它小的(left)和右边第一个比它小的(right)则right-left-1就是以这个柱子为最低高度的矩形的宽度
    所有的这些宽度*高度里的最大值就是我们的答案*/
    public int largestRectangleArea(int[] heights) {
        /**如果只有一个,那没啥说的,返回它的高度就行了,因为它的宽度是1 */
        if(heights.length == 1) {
            return heights[0];
        }
        /**如果是两个,我们可以特殊处理也可以不特殊处理,这里我不特殊处理了,直接用单调栈来处理
        单调栈的核心是nearLess数组,我们使用单独的方法去求这个*/
        int[][] nearLess = getNearLess(heights);
        /**有了这个数组之后我们就可以直接比较求答案了 */
        int ans = 0;
        for(int i = 0; i < heights.length; i++) {
            /**我们这里left和right可以直接用,因为我们在getNearLess里已经取巧处理了 */
            int left = nearLess[i][0];
            int right = nearLess[i][1];
            ans = Math.max(ans, (right - left - 1) * heights[i]);
        }
        return ans;
    }

    public int[][] getNearLess2(int[] heights) {
        /**定义返回结果 */
        int[][] nearLess = new int[heights.length][2];
        /**定义单调栈,我们栈里的数据是栈底到栈顶依次变大的,也就是栈顶是最小值,如果出现更小的就把大的弹出 */
        Stack<Integer> minStack = new Stack<>();
        /**遍历数组依次入栈 */
        for(int i = 0; i < heights.length; i++) {
            while(!minStack.isEmpty() && heights[minStack.peek()] > heights[i]) {
                /**把大的弹出 */
                int popIndex = minStack.pop();
                /**i是造成popIndex这个数弹出的,也就是右边第一个小于它的数的下标 */
                nearLess[popIndex][1] = i;
                /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
                nearLess[popIndex][0] = minStack.isEmpty()? -1 : minStack.peek();
            }
            /**当前已经满足放入的条件了,放入当前数 */
            minStack.push(i);
        }
        /**结算栈中剩余的元素 */
        while(!minStack.isEmpty()) {
            int popIndex = minStack.pop();
            /**剩余需要结算的数右边没有比它小的,这里就写heigths.length了,这里是为了主方法计算方便,一般别的地方我写-1 */
            nearLess[popIndex][1] = heights.length;
            /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
            nearLess[popIndex][0] = minStack.isEmpty()? -1 : minStack.peek();
        }
        return nearLess;
    }

    public int[][] getNearLess(int[] heights) {
        /**定义返回结果 */
        int[][] nearLess = new int[heights.length][2];
        /**定义单调栈,我们栈里的数据是栈底到栈顶依次变大的,也就是栈顶是最小值,如果出现更小的就把大的弹出,这里我替换成数组用于节约常数时间 */
        int[] minStack = new int[heights.length];
        int stackSize = 0;
        /**遍历数组依次入栈 */
        for(int i = 0; i < heights.length; i++) {
            while(stackSize != 0 && heights[minStack[stackSize - 1]] > heights[i]) {
                /**把大的弹出 */
                int popIndex = minStack[--stackSize];
                /**i是造成popIndex这个数弹出的,也就是右边第一个小于它的数的下标 */
                nearLess[popIndex][1] = i;
                /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
                nearLess[popIndex][0] = stackSize == 0? -1 : minStack[stackSize - 1];
            }
            /**当前已经满足放入的条件了,放入当前数 */
            minStack[stackSize++] = i;
        }
        /**结算栈中剩余的元素 */
        while(stackSize != 0) {
            int popIndex = minStack[--stackSize];
            /**剩余需要结算的数右边没有比它小的,这里就写heigths.length了,这里是为了主方法计算方便,一般别的地方我写-1 */
            nearLess[popIndex][1] = heights.length;
            /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
            nearLess[popIndex][0] = stackSize == 0? -1 : minStack[stackSize - 1];
        }
        return nearLess;

    }
}
相关推荐
小陈的进阶之路2 分钟前
蓝桥杯备赛(c/c++)
职场和发展·蓝桥杯·排序算法
CocoaAndYy9 分钟前
设计模式-建造者模式
java·设计模式·建造者模式
雨绸缪15 分钟前
ABAP 的 “小技巧 ”和 “陷阱 ”以及新语法
后端·代码规范·掘金·金石计划
汪汪君。19 分钟前
求矩阵的鞍点
c++·算法·矩阵
碳苯21 分钟前
【rCore OS 开源操作系统】Rust 异常处理
开发语言·人工智能·后端·rust·操作系统·os
程序员大金35 分钟前
基于SpringBoot+Vue+MySQL的药品销售管理系统
java·vue.js·spring boot·mysql·tomcat·intellij-idea·mybatis
尘浮生38 分钟前
Java项目实战II基于Java+Spring Boot+MySQL的桂林旅游景点导游平台(源码+数据库+文档)
java·开发语言·数据库·spring boot·mysql·maven·intellij-idea
艾伦~耶格尔1 小时前
Maven 高级之分模块设计与继承、聚合
java·后端·学习·maven·项目管理
多多*1 小时前
OJ在线评测系统 微服务高级 网关跨域权限校验 集中解决跨域问题 拓展 JWT校验和实现接口限流降级
java·开发语言·微服务·云原生·架构·maven
另类程序员1321 小时前
安装jdk安装开发环境与maven
java·开发语言