力扣LeetCode #84 柱状图中最大的矩形(LargestRectangleArea)

- 题目描述

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。

来源:LeetCode

- 示例

输入: [2,1,5,6,2,3]
输出: 10

- 思路分析

  • 思路1:暴力双循环法。最后有几个例子无法通过,会超时。
  • 思路2:单调栈法。选一个柱子,以这个柱子i的高度作为矩形的固定高度h。由于要面积尽可能大,所以我们希望矩形尽可能宽。当高度确定的时候,从柱子i能够左右延伸的最远距离是遇到的高度小于h的柱子,注意计算矩形并不包含这个边界柱。计算左右两边能延伸的最远距离就是用单调栈法。详解看官方的吧,有例子,说得很详细。

- JAVA实现

class Solution {
    public int largestRectangleArea(int[] heights) {
        /*
        //双重循环法,超时
        int minH = 0;
        int maxArea = 0;
        for(int i=0; i<heights.length; i++) {
            if(heights[i] <= minH) continue;
            for(int j=i; j<heights.length; j++) {
                if(j == i) minH = heights[i];
                else minH = Math.min(minH, heights[j]);
                int area = minH*(j-i+1);
                if(area>maxArea) maxArea = area;
            }
        }
        return maxArea;  
        */
        
        Stack stack = new Stack();
        int[] left = new int[heights.length];  //记录每个柱子向左能延伸的最远距离:即向左遇到的第一个高度小于这个柱子高度的柱子。
        int[] right = new int[heights.length];
        
        left[0] = -1;    
        stack.push(0);
        for(int i=1; i<heights.length; i++) {
            while(!stack.empty() && heights[i] <= heights[(int)stack.peek()]) stack.pop();
            if(stack.empty()) left[i] = -1;
            else left[i] = (int)stack.peek(); 
            stack.push(i);
        } 
        
        while(!stack.empty()) stack.pop();  //清空栈
        
        right[heights.length-1] = heights.length;
        stack.push(heights.length-1);
        for(int j=heights.length-2; j>=0; j--) {
            while(!stack.empty() && heights[j] <= heights[(int)stack.peek()]) stack.pop();
            if(stack.empty()) right[j] = heights.length;
            else right[j] = (int)stack.peek();
            stack.push(j);
        }
        
        int maxA = 0;
        for(int m=0; m<heights.length; m++) {
            int area = (right[m] - left[m] - 1)*heights[m];
            if(area>maxA) maxA = area;
        }
        return maxA;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值