leetcode 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.

For example,
Given heights = [2,1,5,6,2,3],
return 10.
012345
215623
dp[i][j] : min(nums(i,j)) * (j - i)
01:2
02:2
03:3
04:4。。。
如果能快速求出min(nums(i,j))就很好了 也就是记录每个子序列的最小值
这个还是可以动态规划的 维护一个treeset
但是这个方法并不好 看了网上的博客,好难 总结一下:
27564
2756是2*4 , 27564是2*5, 2*4这个矩形其实相对于2*5是冗余计算的
2的最大矩形是2*5=10
7的最大矩形是7*1 = 7
5的最大矩形是5*3 =15
6的最大矩形是6
4的最大矩形是4*4 = 16
以每个高度为中心看其能延伸多长 这个矩形一定是某个ij的最大矩形 这样大概是o(N) 但是也可能是o(N^2)

这里写图片描述
首先 我们画出一个模拟的山峰 我们要做的就是在这里画出一个面积最大的矩形 当然矩形不能超出山峰的边界
这里写图片描述
那么我们首先可能会想到 沿着山峰的这条边 每隔一段距离 画一个矩形出来 看看矩形的大小如何变化 要找到这个矩形 就要找到当前右边在哪里 可以看到我们如果直接找的话顺序就是图中123的顺序 先针对1去找两边的右1 然后是去找右2 然后是右3 那么这个关键 就是 找右1的时候已经扫描一遍了 找2的时候再扫描一遍 这个扫描的时候是有重复的 有没有什么办法让扫描的效率比较高呢?比如看到峰值 下滑 先看到右边的3 让它去对应左边的3 然后看到右边的2 让它对应左边的2 然后还没找到1就又开始上升 所以先不管1
这里写图片描述
总之下了这个山峰之后左边遗留一部分红色没算矩形 中间的黄色部分已经计算完毕了 现在又进来一段 红色等待计算
这里写图片描述
然后又有一段下降的匹配掉了第二段红色的一部分 又留下了一部分
并且进来了第三段红线等待计算

到这里应该可以想到用什么数据结构存储红线了

上升就进栈 到了峰值 下降阶段出栈顶 并且每个出去的算一下矩形面积
再上升再进栈 再下降再出栈
一直到最后栈空 结束

最终还是抄了源码 真是太牛逼了。。。

public int largestRectangleArea(int[] heights) {
        List<Integer> heightList = new ArrayList<Integer>();
        for(int height:heights) heightList.add(height);
        heightList.add(0);
        Stack<Integer> stack = new Stack<Integer>();  
        int sum = 0;  
        for (int i = 0; i < heightList.size(); i++) {  
            if (stack.empty() || heightList.get(i) > heightList.get(stack.lastElement())) 
                stack.push(i);  
            else {  
                int tmp = stack.lastElement();  
                stack.pop();  
                sum = Math.max(sum, heightList.get(tmp)*(stack.empty()? i : i-stack.lastElement()-1));  
                    i--;  
            }  
         }  
         return sum;  
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值