zoukankan      html  css  js  c++  java
  • 【Largest Rectangle in Histogram】cpp

    题目:

    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.

    代码:

    class Solution {
    public:
        int largestRectangleArea(vector<int>& height) {
                int ret = 0;
                const size_t len = height.size();
                if (!len) return len;
                int *dp_left = new int[len](), *dp_right = new int[len]();
                dp_left[0] = 0;
                dp_right[len-1] = len-1;
                // dp_left : record the left most position of height arr that the curr element can reach 
                for ( size_t i = 1; i < len; ++i ){
                    int left = i;
                    while ( left>0 && height[i]<=height[left-1] ) left = dp_left[left-1];
                    dp_left[i] = left;
                }
                // dp_right : vice versa
                for ( int i = len-2; i >0; --i) {
                    int right = i;
                    while ( right<len-1 && height[i]<=height[right+1] ) right = dp_right[right+1];
                    dp_right[i] = right;
                }
                // get the largest rectangle
                for ( size_t i = 0; i < len; ++i ) ret = std::max( ret, (dp_right[i]-dp_left[i]+1)*height[i] );
                delete[] dp_left;
                delete[] dp_right;
                return ret;
        }
    };

    tips:

    采用dp的思路,主要参考 http://www.acmerblog.com/largest-rectangle-in-histogram-6117.html

    遍历三次:

    1. left to right : dp_left[i]数组存放height[i]向左最多能推到哪个位置

    2. right to left : dp_right[i]数组存放height[i]向右最多能推到哪个位置

    注意,不论是dp_left还是dp_right存放都是height数组的绝对位置(一开始dp_right一直存放相对位置,导致不能AC)

    这里虽然for循环中又有while循环,但是复杂度并不是O(n²),原因并不是一个挨着一个跳的,而是用之前比较的结果(dp_left,dp_right)跳的。

    3. 最后走一遍dp,记录最大值

    ==========================================

    自己找虐,又去追了一下stack的解法。自己写了很久并没有通过,学习了下网上的代码。

    class Solution {
    public:
        int largestRectangleArea(vector<int>& height) {
            int ret = 0;
            height.push_back(0);
            stack<int> sta;
            for ( int i = 0; i < height.size(); )
            {
                if ( sta.empty() || height[i]>height[sta.top()] )
                {
                    sta.push(i++);
                }
                else
                {
                    int tmp = sta.top();
                    sta.pop();
                    ret = std::max( ret, height[tmp]*(sta.empty() ? i:i-sta.top()-1 ));
                }
            }
            return ret;
        }
    };

    核心思想就是:维护一个递增的stack。

    1. 一旦遇到不能维持递增stack的元素了,就逐个往外弹出,直到能压进去。

    2. 往外弹一个元素,就意味着这个元素不能再留着了,因此就计算一下包含弹出的这个元素在内,最大的rectangle是多少。

    这里可能有一个疑问:把这个元素弹出来,那万一这个元素跟后面的元素能配上,获得更大大面积了呢?

    这个是不可能发生的,因为这个元素能弹出来,必然是在其后面遇上了比它小的元素(阻断了被弹出的元素与后面的联系),因此这种算法是合理的。完毕。

    ===============================================

    第二次过这道题,只记得用递增的stack来做了。

    (1)stack里面存的是元素的下标

    (2)先弹出来栈顶的元素,再看新的栈顶的元素(刚弹出来的这个元素往前能推到哪里)

    class Solution {
    public:
        int largestRectangleArea(vector<int>& height) {
                if (height.size()==0) return 0;
                height.push_back(0);
                int ret = 0;
                stack<int> sta;
                for ( int i=0; i<height.size(); ++i )
                {
                    if ( sta.empty() || height[sta.top()]<height[i] )
                    {
                        sta.push(i);
                    }
                    else
                    {
                        while ( !sta.empty() && height[sta.top()]>=height[i] )
                        {
                            int tmp = sta.top();
                            sta.pop();
                            if ( sta.empty() )
                            {
                                ret = max(ret, i*height[tmp]);
                            }
                            else
                            {
                                ret = max(ret, (i-sta.top()-1)*height[tmp]);
                            }
                        }
                        sta.push(i);
                    }
                }
                return ret;
        }
    };
  • 相关阅读:
    poj3041(最小顶点覆盖)
    High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件
    hdu 3183 A Magic Lamp(RMQ)
    Android studio 中创建AIDL Service
    cocos2d-x 3.0正式版 cmd创建project以及一键创建project
    【Machine Learning】决策树案例:基于python的商品购买能力预测系统
    【Machine Learning】机器学习及其基础概念简介
    【Machine Learning】Python开发工具:Anaconda+Sublime
    【HanLP】HanLP中文自然语言处理工具实例演练
    【HanLP】资料链接汇总
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4499450.html
Copyright © 2011-2022 走看看