84. Largest Rectangle in Histogram

题目链接

84. Largest Rectangle in Histogram

题目描述

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

在这里插入图片描述

The largest rectangle is shown in the shaded area, which has area = 10 unit.
在这里插入图片描述

Example:

Input: [2,1,5,6,2,3]
Output: 10

解答

这个题目是单调栈的问题,我们先假设自己的heights数组为单调递增的,例如: 1,3,5,6
那么最大的面积计算方法有四种,1 * 4 ; 3 * 3 ; 5 * 2; 6 * 1,也就是(length - index) * height[index]

单调递增栈的主要算法流程如下:
假设栈中保存的是元素的下标。
我们假设变量如下: 当前元素为curr, 栈顶元素为top,第二栈顶元素为top2
如果当前栈为空,或者currtop大或者等于top,直接入栈。
如果当前栈不为空,并且当前元素比栈顶元素小,则栈顶元素出栈。我们需要现在计算以栈顶元素为顶峰的矩形面积,根据单调递增栈的特性,我们知道,以栈顶元素为分割线,左边区域为:栈左边top2到栈顶元素之间的全部是比栈顶元素大的,右边区域为:栈顶元素到当前元素之间全部是比栈顶大的,因此,矩形区域的长度为:width = 左边+ 右边 = [Index(栈顶) - Index(top2)] + [Index(curr) - Index(top)] - 1 = Index(curr) - Index(top2) - 1;
因此面积就为width * height[Index(栈顶)]。

单调递增栈的特性就是:可以找到左起第一个比当前数字小的元素。假设栈低元素下边为0,栈顶元素下标为top, 则栈中下标为i的元素满足如下性质: (i-1)元素到第i元素之间消失的元素都比第i个元素大,因此也一定都比第(i-1)个元素大,第i个元素到第(i+1)个元素之间的元素也一定都比第i个元素和第(i+1)个元素之间的元素大。简单来说,就是栈中两个相邻元素之间消失的元素一定都比两边的元素大。

单调递减栈的特性就是:可以找到坐起第一个比当前数字大的元素

现在模拟一下题目中给出的例子:
index = 0, stack为空{},因此,直接将2的下标push进去,当前栈为{0}
index=1, stack{0}, 因为h[top] > h[index] 因此,直接将0出栈,maxArea= 1 * 2 = 2;将1入栈
index=2, stack{1}, 接下来5,6都是递增的,因此栈中元素变为{1,2,3}
index=4, stack{1,2,3},栈顶元素为6,当前元素为2,因此,6对应的下标3出栈,maxArea = 6 * (4 - 2 - 1) =6,之后,继续出栈,出栈的元素下标为2,maxArea= 5*(4 - 1 - 1) = 10,之后,栈顶对应的元素为1,比小标为4的元素2大,因此入栈,当前栈为stack{1,4}
index=5, stack{1,4} ,栈顶对应元素为1,当前元素为3,因此,入栈,{1,4,5}
之后index=6,对应元素为0(注意,这是我们自己设置的变量,为了使栈中的元素能全部出栈),因为0是最小的,因此能保证其中的元素全部出栈,从而遍历所有的情况。

代码如下

class Solution {
    public int largestRectangleArea(int[] heights) {
        if(heights.length == 0) {
        	return 0;
        }
        if(heights.length == 1) {
        	return heights[0];
        }
        Stack<Integer> stack = new Stack<Integer>();
        int ans = 0;
        for(int i = 0; i<= heights.length; i++) {
        	int h = (i == heights.length) ? 0 : heights[i];
        	if(stack.isEmpty() || heights[stack.peek()] <= h) {
        		stack.push(i);
        	}else {
        		while(!stack.isEmpty() && heights[stack.peek()] >= h) {
        			int curr = stack.pop();
        			if(stack.empty()) {
        				ans = Math.max(ans, heights[curr] * (i));
        			}
        			else {
        				ans = Math.max(ans, heights[curr] * (i - 1 - stack.peek()));
        			}
        		}
        		stack.push(i);
        	}
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值