• LeetCode84:柱状图中最大的矩形


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

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

      

    以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

    首先定义:

      对柱形图中的一个矩形i来说,我们计算以heights[i]为高的矩形的最大面积时,以i为起点,向左找到第一个小于heights[i]的矩形j,向右找到第一个小于heights[i]的矩形k。(j,k)区间,也即[j+1,k-1]所围成的以heights[i]的矩形就是i的最大矩形。当然,这个矩形面积不一定是整个柱形图中的最大矩形,但一定是i的最大矩形,因为i是[j+1,k-1]区间内最短的一个,如果这个区间内有某个矩形z的高heights[z]小于heights[i],则区间所围成的矩形最大面积应该以heights[z]为高,因为z才是真正的短板。

      因此,如果我们要计算整个柱形图中的最大面积,其实只要找到所有的以i(i=0....n-1)的高为高的最大矩形,在里面选一个就好了。

      实际操作上可以对每个矩形都向左找一个上界,向右找一个下界,但这样时间复杂度实际上是处于O(n^2)。

      因此可以考虑用一个单调递增的栈,栈中存储的是矩形的索引。

    首先为什么要选取一个单调递增栈呢?因为如果采取单调递增栈,则对栈中任意一个元素i来说,i以前入栈的元素一定都比它矮,也就是说我们不用去寻找上界,它的上界一定就是第i-1个元素。

    然后为什么要存储矩形的索引呢?因为根据索引我们既可以马上得到它的高heights[i],也可以马上得到它的宽,只要用索引加减就可以了。

    计算流程:

    1).最开始入栈-1(-1的作用是当栈中只有一个矩形时,它的上界就是-1,不然栈中只有这一个矩形的话上界不方便计算)。

    2).如果当前矩形i的高>=heights[aux.top()],则入栈。这是为了保持栈的单调递增性质。

    3).如果当前矩形i的高<heights[aux.top()],则将aux.top()出栈,对出栈的这个元素j来说,他在栈中的前一个元素a一定是小于它的,所以一定是它的上界。现在的这个元素i的高也一定是小于它的,所以是它的下界,因此以aux.top()为高的最大矩形的上下界就已经确定下来为(a,i),也就是[a+1,i-1]了,对这个矩形j来说,它的最大面积为heights[j]*(i-1-(a+1)+1)。计算得到这个面积area后,将他与max作对比并做记录。继续与现在的aux.top()和i做对比,出栈直到heights[aux.top()]<heights[i]时,在将i入栈。

    4)循环这个过程。当然,如果说矩形的最后几个元素高都是递增的,最后会发现栈中除-1外还有元素,因此在最开始我们就在heights中加入一个0,这个0的作用就是用于最后对付栈未空的情况,因为0一定可以作为矩形们的下界。

    代码:

    class Solution {
    public:
        int largestRectangleArea(vector<int>& heights) {
    		if(heights.size()==0)
    			return 0;
    		stack<int> aux;
    		int max=INT_MIN;
    		aux.push(-1);
    		heights.push_back(0);
    		for(int i=0;i<heights.size();i++)
    		{
    			if(aux.top()==-1||heights[aux.top()]<=heights[i])
    				aux.push(i);
    			else
    			{
    				while(aux.top()!=-1&&heights[aux.top()]>heights[i])
    				{
    					int h=heights[aux.top()];
    					aux.pop();
    					int area=h*(i-aux.top()-1);
    					if(area>=max)
    						max=area;
    				}
    				aux.push(i);
    			}
    		}
    		if(max<=0)
    			return 0;
    		return max;
        }
    };
    

      

  • 相关阅读:
    识别IE11浏览器
    国庆过后老革命
    有些东西再忙也要做
    云计算
    SVN下Update出现代码文件删除状态问题
    如何避免历史回退到登录页面
    CodeSmith连Oracle
    NHibernate直接执行SQL进行插入
    nhibernate实体类主键ID赋值问题
    NHibernate不支持复杂的linq,就一定要用DataTable这么低级吗
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11287822.html
Copyright © 2020-2023  润新知