题目链接:https://leetcode.com/problems/maximal-rectangle/
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.
思路:这一题是Maximal Square的加强版,是给定一个0和1的矩阵,找到一个最大全为1的矩形的面积。还有一题是这一题的前提,Largest Rectangle in Histogram,解决了前置的题目,这一题就很容易想到要怎么做了。写到这里发现我largest rectangle in Histogram的解题报告怎么不见了,我记得刚才还在审核中啊,怎么会不见了?好吧,一会再补上吧!
在largest rectangle in Histogram题目中是给一个直方图,让求最大的矩形的面积
而在本题中我们可以将每一行向上有多少个1的值看做是一个直方图的长度,这样就可以每一行调用上一题的函数,比较出最大的矩形面积即可。在计算每一行向上有多少个一的时候如果我们直接每一行都向上扫描,则扫描的总时间复杂度为O(m * n * m),应该是无法通过所有数据的。借助动态规划可以将时间复杂度降为O(m * n)。引入一个辅助数组hash[][],记录当前位置向上有多少个1,在计算其值的时候有两种情况:
1. 如果matrix[i-1][j] = 1, 则hash[i][j] = hash[i-1][j],因为hash[i][j]的值只与hash[i][j]有关,即只与竖直向上一个位置有关,所以我们hash数组只增加一行,列则与matrix保持一致
2. 如果matrix[i-1][j] = 0,则hash[i][j] = 0;
这样将每一行的hash[i]作为一个直方图各个bar的值传入上一题的函数即可得到在这一行的最大面积,遍历所有行即可找到最大的面积。总的时间复杂度为O(m*n),空间复杂度为O(m*n).
代码如下:
class Solution { public: int getMaxArea(vector<int>& hash)//求一个直方图中最大的矩形面积 { stack<int> st; hash.push_back(0); int maxArea = 0; int i = 0; while(i < (int)hash.size()) { if(st.empty() || hash[st.top()] < hash[i]) st.push(i++); else//如果遇到比栈顶元素小的值,则找到了比栈顶元素小的左右元素的位置,即可计算以栈顶元素为最低bar的矩形面积 { int top = st.top(); st.pop(); maxArea = max(maxArea, hash[top]* (st.empty()?i:(i-st.top()-1)));//计算以hash[top]为最小bar的矩形面积 } } hash.pop_back(); return maxArea; } int maximalRectangle(vector<vector<char>>& matrix) {//求一个矩阵的最大含1的矩形面积 if(matrix.size() == 0) return 0; vector<int> tem(matrix[0].size(), 0); vector<vector<int>> hash(matrix.size()+1, tem);//记录向上有多少个1 int maxArea = 0; for(int i = 1; i <= (int)matrix.size(); i++) { for(int j =0; j< (int)matrix[0].size(); j++)//更新一行向上有多少个1 { if(matrix[i-1][j] == '1') hash[i][j] = hash[i-1][j]+1; else hash[i][j] = 0; } maxArea = max(maxArea, getMaxArea(hash[i]));//更新最大面积 } return maxArea; } };