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

方法1: stack

思路:

主要破题点在于,对于某一个位置的楼,我们要找以它为顶点的长方形,只需要知道它左边的低点(相对自己)和右边的低点,这个范围是能取到的最大长度。同时要注意,再往左边的低点也需要依次保留,以计算高度虽然更低,但长度更宽的长方形。那么如何在一次遍历中追溯两个低点?还要依次记录前序所有低点?这就用到了stack。具体操作如下:

  1. 如果当前点高于前点,或者前点不存在,可以推入栈(因此我们保证了栈内严格递增)。
  2. 如果当前点低于了当前栈顶(注意不是index上的前点),那说明它已经成为了之前某些高度的右低点,对于这些长方形,已经可以开始计算。
  3. 具体是哪些长方形?以栈内第一个元素为height,第二个元素为左低点的长方形。而这样的长方形不止一个,对于栈内的所有元素,只要作为左低点比当前右低点还高,就还没有限制住左边的最远位置,需要继续查找。如果pop出来的左低点已经比右低点还低,右低点成为了限制因素,可以继续往前搜。
  4. 所以什么时候才update一下max area?一定是等到最有可能update的时候才update一下。也就是说,当没有出现左边的更低的时候,且我们已知中间没有再低的点,那么机制目前的限制因素都是right。但我们着急update吗?还没到时候,直到遇到左低点已经比右低点还低,我们才能确定以右地点为高度的长方形到头了,再往左边只能是left说了算。而这些left说了算的rectangle,什么时候被计算了????
  5. 当遍历到最后一个元素,需要开始最后一轮计算。此时处理的是“以0为右低点”,也就是以最右点为右届的所有长方行面积,需要将栈pop清空,此间的长方形每一个都有可能更新最大面积。

易错点

  1. 栈内存的是index
  2. 处理空栈情况
  3. 最好不要用for loop,除非里面套一个while loop。弹栈的动作是一个持续过程,直到新的左低点比当前右低点更低while loop可以很好的解决这个问题。

Complexity

Time complexity: O(n)
Space complexity: O(n)

class Solution1 {
public:
    // 方法1:
    int largestRectangleArea1(vector<int>& heights) {
        stack<int> myStack;
        
        int maxArea = 0;
        int area = 0;
        int i = 0; // position the current index in the histogram
        
        while (i < heights.size()){
        
        // for (i = 0; i < heights.size(); i++){
            // note myStack store the index, not the actual value
            // heights[use myStack.top()]
            if (myStack.empty() || heights[myStack.top()] <= heights[i] ){
                // If stack is empty or value at index of stack is less than or equal to value at current index, push this into stack.
                myStack.push(i++);
            }
            else {
                // else the current index position start to decrease, potential change of maxArea
                int top = myStack.top();
                myStack.pop();
                
                if (myStack.empty()){
                    // here since myStack is empty, don't need to mind the left shortest one, the width of rectangle has height = myStack.top() is equal to (i - 1 + 1) * 2 
                    area = heights[top] * i;
                }
                else {
                    //     height     *       width
                    area = heights[top] * (i - myStack.top() - 1);
                }
                
                if ( area > maxArea) {
                    maxArea = area;
                }
                
                
            }
        }
        while (!myStack.empty()){
            int top = myStack.top();
            myStack.pop();
            
            if (myStack.empty()){
                area = heights[top] * i;
            }
            else {
                area = heights[top] * (i - myStack.top() - 1);
            }
            if (area > maxArea) {
                maxArea = area;
            }
        }
        return maxArea;
    }

二刷:

class Solution {
public:
    // 方法1:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> st;
        int i = 0, maxArea = 0, area = 0, n = heights.size();
        while (i < n) {
            if (st.empty() || heights[st.top()] < heights[i]) {
                st.push(i++);
            }
            else {
                int h = heights[st.top()]; 
                st.pop();
                if (st.empty()) area = i * h;
                else {
                    area = (i - st.top() - 1) * h;
                }
                
                if (area > maxArea) maxArea = area;
            }
        }
        
        while (!st.empty()) {            
            int h = heights[st.top()];
            st.pop();
            if (st.empty()) area = i * h;
            else {
                area = (i - st.top() - 1) * h;
            }
            
            if (area > maxArea) maxArea = area;
        }
        return maxArea;
    }
};

方法2:

思路:

遍历右端点,在内循环遍历左端点。用到了小优化:如果右点比右边的点还低,那么可以跳过,因为更右边一定存在更大的长方形。

Complexity

Time complexity: O(n^2)
Space complexity: O(1)

// 方法2: 非最优解
    int largestRectangleArea(vector<int>& heights) {
        if (heights.size() == 0) return 0;
        int maxArea = 0;
        for (int cur = 0; cur < heights.size(); cur++){
            int minHeight = heights[cur];
            for (int idx = cur; idx >= 0; idx--){
                minHeight = min(minHeight, heights[idx]);
                maxArea = max(maxArea, minHeight * (cur - idx + 1));
            }
        }
        return maxArea;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值