84. 柱状图中最大的矩形

单调栈:leetcode 84. 柱状图中最大的矩形/85最大矩形_算法

遍历数组,以每一个元素作为高,向左右两边拓展,遇到第一个比该元素小的位置停下

单调栈:leetcode 84. 柱状图中最大的矩形/85最大矩形_算法_02

 图片源自leetcode 力扣

 一.暴力解法(超时)

遍历数组,以每一个元素作为高,向左右两边拓展,遇到第一个比该元素小的位置停下

时间复杂度O(n*n)

空间复杂度O(1)

代码:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
//最大面积,初始为0
int maxa=0;
for(int i=0;i<heights.size();i++)
{
    //从高度为heights[i]向两边扩散,直到高度小于heights[i]时停止,求面积
    int height=heights[i];
//边界为(left,right)
    int left=i;
    int right=i;
//求左边界left
    while(left>=0&&heights[left]>=heights[i])
    {
        left--;
    }
//求右边界right
    while(right<=heights.size()-1&&heights[right]>=heights[i])
    {
        right++;
    }
//更新最大面积
    maxa=max(maxa,(right-left-1)*heights[i]);
    
}
return maxa;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

二.单调栈

单调栈模板:

stack<int>st;
vector<int>vec(数组元素个数);
//△需要变动的地方
△for(i遍历数组)
while (!st.empty()&&△st.top()nums[i])//栈顶元素与x比较  st.pop();
        //如果栈为空,说明没有左面比当前元素更小的元素
if (st.empty()) vec[i]=-1 ;
else  △vec[i]=st.top();
//如果栈不为空,则栈顶就是左面第一个比当前元素更小的元素	
//当前元素进栈
△st.push(nums[i]);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

模板说明:

一共有4种情况:

给定一个数组nums:

(1)vec保存nums每个元素左边第一个比该元素小的元素:

       ○正序遍历数组:for(int i=0;i<nums.size();i++)

       ○单调递增栈:st.top()>=nums[i]

  (2)vec保存nums每个元素左边第一个比该元素大的元素:

      ○ 正序遍历数组:for(int i=0;i<nums.size();i++)

      ○ 单调递减栈:st.top()<=nums[i]

(3)vec保存nums每个元素右边第一个比该元素小的元素:

   ○    逆序遍历数组:for(int i=nums.size()-1;i>=0;i--)

  ○        单调递增栈:st.top()>=nums[i]

(4)vec保存nums每个元素右边第一个比该元素小的元素:

     ○   逆序遍历数组:for(int i=nums.size()-1;i>=0;i--)

     ○      单调递增栈:st.top()>=nums[i]

如果vec存放的是下标:

变动两个地方:

○改成nums[st.top]与nums[i]比较

○最后改为st.push(i)

思路:

用两个数组left_min和right_min存放heigts[i]左边和右边第一个比它小的元素的下标

如果不存在返回-1,nums.size()

则以heights[i]为高的最大矩形面积为(right_min[i]-left_min[i]-1)*heights[i]

代码:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
//left_min记录左边第一个比heights小的下标,如果没有返回-1
vector<int>left_min(heights);
//right_min记录右边第一个比heights小的下标,如果没有返回-1
vector<int>right_min(heights);

stack<int>st;
for(int i=0;i<heights.size();i++)
{
    while(!st.empty()&&heights[st.top()]>=heights[i])
    st.pop();
    if(st.empty())
    {
        left_min[i]=-1;
    }
    else
    {
        left_min[i]=st.top();
    }
    st.push(i);
}
stack<int>st1;
for(int i=heights.size()-1;i>=0;i--)
{
    while(!st1.empty()&&heights[st1.top()]>=heights[i])
    st1.pop();
    if(st1.empty())
    {
        right_min[i]=heights.size();
    }
    else{
        right_min[i]=st1.top();
    }
    st1.push(i);
}
int maxa=0;

for(int i=0;i<heights.size();i++)
{

  maxa=max((right_min[i]-left_min[i]-1)*(heights[i]),maxa);

}
return maxa;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.

 85. 最大矩形

单调栈:leetcode 84. 柱状图中最大的矩形/85最大矩形_遍历数组_03

 

单调栈:leetcode 84. 柱状图中最大的矩形/85最大矩形_算法_04

 矩阵的每一层转换为直方图,传入84题的函数求解:

如果mat[i][j]=0,height[j]=0

如果mat[i][j]=1,height[j]++

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
int maxa=0;
if(matrix.size()==0)
return 0;
vector<int>height(matrix[0].size(),0);
for(auto i:matrix)
{
    for(int j=0;j<i.size();j++)
    {
        if(i[j]=='0')
        height[j]=0;
        else
        height[j]++;
    }
    maxa=max(maxa,largestRectangleArea(height));
}
return maxa;
    }
     int largestRectangleArea(vector<int>& heights) {
//left_min记录左边第一个比heights小的下标,如果没有返回-1
vector<int>left_min(heights);
//right_min记录右边第一个比heights小的下标,如果没有返回-1
vector<int>right_min(heights);

stack<int>st;
for(int i=0;i<heights.size();i++)
{
    while(!st.empty()&&heights[st.top()]>=heights[i])
    st.pop();
    if(st.empty())
    {
        left_min[i]=-1;
    }
    else
    {
        left_min[i]=st.top();
    }
    st.push(i);
}
stack<int>st1;
for(int i=heights.size()-1;i>=0;i--)
{
    while(!st1.empty()&&heights[st1.top()]>=heights[i])
    st1.pop();
    if(st1.empty())
    {
        right_min[i]=heights.size();
    }
    else{
        right_min[i]=st1.top();
    }
    st1.push(i);
}
int maxa=0;

for(int i=0;i<heights.size();i++)
{

  maxa=max((right_min[i]-left_min[i]-1)*(heights[i]),maxa);

}
return maxa;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.