1 直方图最大矩形面积
剑指 Offer II 039. 直方图最大矩形面积
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
//单调递增栈
stack<int> s;//s中保存的是直方图的索引
s.push(-1);//-1相当于一个sentinel
int maxArea = 0;
for (int i = 0; i < heights.size(); ++i)
{
//若当前柱高<=栈顶柱高,将栈顶柱子出栈,并计算栈顶柱子为顶的最高矩阵面积,直至可入栈
//出栈的目的是在“栈顶->栈底”的方向上找到第一个“高度小于当前柱子的高度”元素,这样,被找到的这个元素和当前元素之间(不含这两个边界元素)夹着的矩形可勾勒出最大面积的矩形
while (s.top() != -1 && heights[s.top()] >= heights[i])
{
int height = heights[s.top()];
s.pop();
int width = i - s.top() - 1;
maxArea = max(maxArea, height * width);
}
//若当前柱高>栈顶柱高,那么该柱子下标入栈
s.push(i);
}
//[1,2,3,4,5]如果按照这个顺序入栈,在上面的过程中是没有机会进行入栈的操作,所以这里还要进行计算一次
while (s.top() != -1)
{
int height = heights[s.top()];
s.pop();
int width = heights.size() - s.top() - 1;
maxArea = max(maxArea, height * width);
}
return maxArea;
}
};
2 最大矩形
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
int area=0;
if(matrix.size() ==0 || matrix[0].size() ==0)
return 0;
int rows = matrix.size();
int cols = matrix[0].size();
vector<int> rectangular(cols);
for(auto& nums:matrix)
{
for(int j=0; j<cols; ++j)
{//把矩阵的矩阵形式,构造成同上一题的“直方图最大矩形”
//也就是每次看一行数据,这一行看做直方图。下一行“1”能和上一行接上就累加,数值就代表矩形高度
//不然下一行的高度就归零。
if(nums[j] == '1')
{
rectangular[j]++;
}
else
{
rectangular[j]=0;
}
}
area = max(area, largestRectangleArea(rectangular));
}
return area;
}
//https://leetcode-cn.com/problems/0ynMMM/ 同样的题目
int largestRectangleArea(vector<int>& heights) {
int len = heights.size();
int area=0;
//栈的目的:不用重复遍历所有匹配,查找可得左右边界情况
stack<int> stk;//存储的是数组的索引值。单调栈,从底到顶,数字为从小到大
stk.push(-1);
int wide, height;
int i=0;
for(; i<len; ++i){//数组遍历(可能会计算之间部分面积)
// 新添加元素小于栈顶元素:栈顶元素为height的,矩形右边界能确定
while(stk.top() !=-1 && heights[stk.top()]>=heights[i]){
height = heights[stk.top()];stk.pop();
wide = i - stk.top()-1;
area = max(area, height*wide);
}
// 新元素大于栈顶元素:栈顶元素为height的矩形右边界没法确定。(直接入栈)
stk.push(i);
}
while(stk.top() != -1){//再遍历栈中剩下的元素,栈中都是从小到大排列,计算面积就很有规律了
height = heights[stk.top()];
stk.pop();
wide = len - stk.top()-1;
area = max(area, height*wide);
}
return area;
}
};