题目链接: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.
思路:三种方法可以做,第一种是比较naive的方式,时间复杂度为O(m*n*n),其中m为行数,n为列数.第二种是动态规划的方式,效率比第一种高出一个数量级,时间复杂度为O(m*n).第三种是将问题转化为另外一题求柱形图组成的最大矩形面积,时间复杂度依然为O(m*n).
第一种方法思路:可以一行一行的遍历数组,维护每个位置到顶部的高度,如果某位置高度大于0就往回扫描到列首,并且维护一个当前最低的高度,这样就可以求出从这个位置到第一列最大的面积.时间复杂是O(m*n*n).空间复杂度O(n).
第二种思路:在上一种方法中我们做了很多重复的计算,就是我们每碰到一个高度不为0的高度就往左搜索找到当前最低的高度然后更新面积,每个高度会被重复计算至多n次.也就是说我们没有利用之前的搜索信息.想想如果在一个位置的高度我们已经知道了,如果我们再知道左右两边高度都大于等于这个高度的边界我们就可以求出以当前高度为最低值的矩形面积了.所以我们需要两个额外的数组来维护一行中每个位置高度的左右边界.
第三种思路:和Largest Rectangle in Histogram 这题的思路是一样的,就是依次把每一行都当成一个柱形图的底,就可以转化为这一题的解法.
代码如下:
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.size() ==0) return 0;
int m = matrix.size(), n = matrix[0].size(), Max = 0;
vector<int> heights(n, 0);
for(int i = 0; i < m ; i++)
{
for(int j = 0; j < n; j++)
{
if(matrix[i][j]=='0') { heights[j] = 0; continue; }
heights[j]++;
for(int k = j, Min = heights[j]; k >=0; k--)
{
Min = min(heights[k], Min);
Max = max(Max, (j-k+1)*Min);
}
}
}
return Max;
}
};
class Solution {
public:
int maximalRectangle(vector<vector<char>>& matrix) {
if(matrix.size() ==0) return 0;
int m = matrix.size(), n = matrix[0].size(), Max = 0;
vector<int> height(n, 0), left(n, 0), right(n, n);
for(int i = 0; i < m; i++)
{
int curLeft = 0, curRight = n;
for(int j = 0; j < n; j++)
{
height[j] = (matrix[i][j]=='0'?0:height[j]+1);
if(height[j]) left[j] = max(left[j], curLeft);
else left[j] = 0, curLeft = j+1;
}
for(int j = n-1; j >= 0; j--)
{
if(height[j]) right[j] = min(right[j], curRight);
else right[j] = n, curRight = j;
}
for(int j = 0; j < n; j++)
if(height[j]) Max = max(Max, (right[j]-left[j])*height[j]);
}
return Max;
}
};
class Solution {
public:
int getMaxArea(vector<int>& hash)//求一个直方图中最大的矩形面积
{
stack<int> st;
hash.push_back(0);
int maxArea = 0, i = 0;
while(i < (int)hash.size())
{
if(st.empty() || hash[st.top()] < hash[i]) st.push(i++);
else
{
int top = st.top();
st.pop();
maxArea = max(maxArea, hash[top]* (st.empty()?i:(i-st.top()-1)));
}
}
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++)
{
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;
}
};
参考:https://leetcode.com/discuss/52670/solution-based-maximum-rectangle-histogram-with-explanation
https://leetcode.com/discuss/20240/share-my-dp-solution