zoukankan      html  css  js  c++  java
  • 代码题(39)— 柱状图中最大的矩形、最大矩形

    1、84.柱状图中最大的矩形

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

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

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

    图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

    示例:

    输入: [2,1,5,6,2,3]
    输出: 10

      方法一:

      考虑回文串的一种从中间往两头找的算法,首先遍历,对于每一个柱状图来说,向左右搜索,直到找到比他小的柱状图(假设为l和r),这样算出该柱状图的对应的矩形的面积为(r-l+1)*heights[cur]。复杂度:O(n*n)。

    class Solution {
    public:
        int largestRectangleArea(vector<int>& heights) {
            if(heights.empty())
                return 0;
            int n = heights.size();
            int res = 0;
            for(int i=0;i<n;++i)
            {
                int j = i-1, k=i+1;
                while(j>=0 && heights[j]>=heights[i])
                    j--;
                while(k<n && heights[k]>=heights[i])
                    k++;
                res = max(res, heights[i]*(k-j-1));
            }
            return res;
        }
    };

      方法二:

      简单来说,维护一个单调栈,如果当前元素大于栈顶元素,则把当前元素的坐标入栈,否则,弹出栈顶元素直到当前元素可入栈。

      在栈顶元素弹出时,把弹出的元素当成最短木板,计算能组成的最大面积是多少。时间复杂度:O(n)。

      为什么栈中保存的是下标而不是数组本身的值? 因为,维护的是递增序列,计算面积总是以短板为高度,中间部分也是取短板的高度,宽度计算在内。

      可以按照下面的理解,以栈中保存值本身而不是下标为例:

      比如2,1,5,6,2,3

      (1)2进栈。s={2}, result = 0

      (2)1比2小,不满足升序条件,因此将2弹出,并记录当前结果为2*1=2。将2替换为1重新进栈。s={1,1}, result = 2

      (3)5比1大,满足升序条件,进栈。s={1,1,5},result = 2

      (4)6比5大,满足升序条件,进栈。s={1,1,5,6},result = 2

      (5)2比6小,不满足升序条件,因此将6弹出,并记录当前结果为6*1=6。s={1,1,5},result = 6,2比5小,不满足升序条件,因此将5弹出,并记录当前结果为5*2=10(因为已经弹出的5,6是升序的)。s={1,1},result = 102比1大,将弹出的5,6替换为2重新进栈。s={1,1,2,2,2},result = 10

      (6)3比2大,满足升序条件,进栈。s={1,1,2,2,2,3},result = 10,栈构建完成,满足升序条件,因此按照升序处理办法得到上述的max(height[i]*(size-i))=max{3*1, 2*2, 2*3, 2*4, 1*5, 1*6}=8<10

      综上所述,result=10

    class Solution {
    public:
        int largestRectangleArea(vector<int>& heights) {
            int res = 0;
            if(heights.empty())
                return res;
            stack<int> st;
            heights.push_back(0);
            for(int i=0;i<heights.size();++i)
            {
                 while (!st.empty() && heights[st.top()] >= heights[i]) {
                    int cur = st.top(); 
                    st.pop();
                    int dis = st.empty() ? i : (i - st.top() - 1);
                    res = max(res, heights[cur] * dis);
                }
                st.push(i);
            }
            return res;
        }
    };

    2、85. 最大矩形

    给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

    示例:

    输入:
    [
      ["1","0","1","0","0"],
      ["1","0","1","1","1"],
      ["1","1","1","1","1"],
      ["1","0","0","1","0"]
    ]
    输出: 6

      此题是上面那道的的扩展,这道题的二维矩阵每一层向上都可以看做一个直方图,输入矩阵有多少行,就可以形成多少个直方图,对每个直方图都调用 “直方图中最大的矩阵”中的方法,就可以得到最大的矩形面积。那么这道题唯一要做的就是将每一层构成直方图,由于题目限定了输入矩阵的字符只有 '0' 和 '1' 两种,所以处理起来也相对简单。

      方法是,对于每一个点,如果是‘0’,则赋0,如果是 ‘1’,就赋 之前的height值加上1。(相当于用“1”来组成直方图)

    class Solution {
    public:
        int maximalRectangle(vector<vector<char>>& matrix) {
            if(matrix.empty())
                return 0;
            int m = matrix.size();
            int n = matrix[0].size();
            vector<int> height(n);
            int res = 0;
            for(int i=0;i<m;++i)
            {
                for(int j=0;j<n;++j)
                {
                    height[j] = (matrix[i][j] == '0'? 0 : (height[j]+1));//如果先加的一行此处位置为0,则就是0,否则在原来的基础上加1
                }
                res = max(res,helper(height) );
            }
            return res;
            
        }
        
        int helper(vector<int>& heights) {
            int res = 0;
            if(heights.empty())
                return res;
            stack<int> st;
            heights.push_back(0);
            for(int i=0;i<heights.size();++i)
            {
                 while (!st.empty() && heights[st.top()] >= heights[i]) {
                    int cur = st.top(); 
                    st.pop();
                    int dis = st.empty() ? i : (i - st.top() - 1);
                    res = max(res, heights[cur] * dis);
                }
                st.push(i);
            }
            return res;
        }
    };
  • 相关阅读:
    java提高篇(二四)-----HashSet
    链表(线性表)
    逆置线性表(线性表)
    Android布局_表格布局TableLayout
    Android布局_布局概述和LinearLayout布局
    Android_用户界面概述和数据单位
    Android_SDK的常用命令
    Android_程序结构分析
    CSS3_边框属性之圆角的基本图形案例
    CSS3_边框属性之圆角
  • 原文地址:https://www.cnblogs.com/eilearn/p/9432240.html
Copyright © 2011-2022 走看看