84. Largest Rectangle in Histogram (Array, Stack; DP)

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 height = [2,1,5,6,2,3],
return 10.

法I: 使用动态规划

class Solution {
public:
    int largestRectangleArea(vector<int> &height) {
        int* l = new int [height.size()]; //状态:向左连续的>=height[i]的最后一个位置
        int* r = new int [height.size()]; //状态:向右连续的>=height[i]的最后一个位置
    
        l[0]=0;
        for( int i =1; i <height.size(); i++) //从左往右扫描
        {
            if(height[i]==0)
            {
                l[i] = 0;
                continue;
            }
            int j = i-1;
            for(; j >= 0; j--){
                if(height[i] <= height[j]) j = l[j]; //用动态规划求l[i]否则会Time Limit Exceeded
                if(height[i] > height[j]) break;
            }
            l[i] = j+1;
        }
        r[height.size()-1]=height.size()-1;
        for(int i =height.size()-2; i >=0; i--){ //从右往左扫描
            if(height[i]==0)
            {
                r[i] = 0;
                continue;
            }
            int j = i+1;
            for(; j <height.size(); j++){
                if(height[i] <= height[j]) j = r[j]; //动态规划
                if(height[i] > height[j]) break;
            }
            r[i] = j-1;
        }
        
        int area;
        int largestArea = 0;
        for(int i = 0; i< height.size(); i++)
        {
            area = (r[i]-l[i]+1) * height[i];
            if(area>largestArea) largestArea = area;
        }
        return largestArea;
    }
};

 

法I的空间负责度是O(n)+O(n), 为了节省空间,可以用stack代替array来存储最高高度的位置。

法II: stack的栈顶元素表示下一个用来计算面积的高度。

进栈条件:当前元素比栈顶元素大或相等, 进栈后 i++

出栈条件:当前元素比栈顶元素小,出栈后 计算面积 i不变(每个元素都要进一次栈,i要等到比自己小的栈顶元素,然后进栈)

为什么要在此时计算面积?

这个高度到i位置截至了,无法往有再延伸,所以要在当下计算面积。

如何界定计算面积时的左界和右界?

  • 左界=新栈顶元素+1
  • 右界=当前位置-1

为什么可以这样?

从新栈顶到i的元素高度都>=height[idx],因为如果其中有<height[idx]的元素,那么idx早就出栈了。

空间复杂度最坏情况也只有O(n)

class Solution {
public:
    int largestRectangleArea(vector<int> &height) {
        if(height.size() == 0) return 0;
         
        int res = 0;
        stack<int> idxStack;
        height.push_back(0); //为了如果在最后height高于栈顶元素,能够再进一次else,把stack中的元素pop出来计算
       
        int i = 0;
        int idx;
        int width;
        while(i < height.size())
        {
            if(idxStack.empty() || height[i] >= height[idxStack.top()]){ //当前高度>=栈顶高度
                idxStack.push(i); //入栈
                i++;
            }
            else{ //高度降低了
                idx = idxStack.top();  
                idxStack.pop(); //出栈
                width = idxStack.empty() ? i : (i-idxStack.top()-1); //界定左右边界
                res = max(res, height[idx] * width); //计算面积,并更新最大面积
            }
        }
        height.pop_back();
        return res;
    }
};

 

posted on 2015-10-08 20:16  joannae  阅读(191)  评论(0编辑  收藏  举报

导航