首页 > 代码库 > leetcode第一刷_Largest Rectangle in Histogram

leetcode第一刷_Largest Rectangle in Histogram

很难的问题,数组线性时间。

属于我之前说的解法的借助辅助空间。给定两个柱子,他们之间的面积由什么确定呢?没错,他们之间的距离和他们之间最矮的那个柱子的高度。我们并不知道这个柱子在什么位置,所以只能遍历,这个复杂度就上去了。那有没有一个方法避免找中间小柱子呢?先想什么情况下不用找。除非你知道枚举出两个位置之间的柱子都比现在这个长。所以想到了用一个栈来保存较长的那些柱子编号。需要保证的一件事是栈里面的柱子高度一定是递增的,每次计算面积的时候是从当前位置往前计算的,计算一次弹出一次,每次都使用栈顶的高度,就像每次都计算被两个较矮柱子包裹的较高柱子们的面积。

整个算法的过程是这样的,一开始栈为空,从左侧开始扫,如果栈空,或者当前扫到的位置比栈顶的高度高,直接把编号入栈。为什么入栈的是编号而不是高度呢?因为求的是面积啊,如果只压入面积,每次得到的就少了一维的信息啊亲。如果当前扫到的柱子比栈顶的低怎么办?出栈。注意在出栈时计算面积是不把当前扫到的位置计算在内的,每次都是把栈顶高度当做最低高度,计算从栈顶位置到当前位置前一位置的面积。这个出栈操作到什么时候呢?到栈空或者当前位置的高度终于比栈顶的高了。扫完一遍之后,栈很可能非空,但里面的柱子肯定是递增的,直接执行一次出栈过程就可以了。

算法为什么是线性的?感觉过程好复杂。不复杂,每个柱子一定只进栈和出栈一次,想起matrix67对这种问题的比喻,100天,我每天谈一个美眉,那么我可能失恋200次吗?大神就是大神。

class Solution {
public:
    int largestRectangleArea(vector<int> &height) {
       int res = 0, tpres, tp;
       int msize = height.size();
       int i = 0;
       stack<int> s;
       while(i<msize){
           if(s.empty()||height[s.top()]<=height[i]){
               s.push(i++);
           }else{
               tp = s.top();
               s.pop();
               tpres = height[tp]*(s.empty()?i:i-s.top()-1);
               res = max(tpres, res);
           }
       }
       while(!s.empty()){
           tp = s.top();
           s.pop();
           tpres = height[tp]*(s.empty()?i:i-s.top()-1);
           res = max(tpres, res);
       }
       return res;
    }
};