Maximal Rectangle -- leetcode

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.


给定一个充满0和1的矩阵,要求出范围全为1的矩阵的面积。


算法一,动态规划

此题,以每行为底,都可以转换成是一个Largest Rectangle in Histogram问题。

每个点,先算出所在矩形的高度,左边界,右边界。然后就能求出这个点所在矩形的面积了。

而高度,左边界,右边界,都可以按照DP思路算出。

已知上一行的高度,如果当前元素为1,则高度+1,否则清0.

left(i,j) = max(left(i-1,j), curleft)   逐步向右收缩其左边矩

right(i,j) = min(right(i-1,j), curright)   逐步向左收缩其右边矩


对curleft设置,如果当前元素为1,则不修改curleft。否则将其置0。置0,意味着下一行,该列时,其左边界,可能延伸至最起始处。即它之前,全为1.

同理,对curright,当前元素为0时,将其置为一个大值。本行度高度为0了。但下一行的,该列时,其右边界,可能延伸到最远处。即在他之后,全为1.


此代码在leetcode上实际执行时间为18ms。

class Solution {
public:
    int maximalRectangle(vector<vector<char> > &matrix) {
        if (matrix.empty() || matrix[0].empty())
            return 0;
        
        int area = 0;
        const int m = matrix.size();
        const int n = matrix[0].size();
        vector<int> height(n);
        vector<int> left(n);
        vector<int> right(n, n);
        
        for (int i=0; i<m; i++) {
            int curLeft = 0;
            for (int j=0; j<n; j++) {
                height[j] = matrix[i][j] == '1' ? height[j]+1 : 0;
                left[j] = matrix[i][j] == '1' ? max(left[j], curLeft) : 0;
                curLeft = matrix[i][j] == '1' ? curLeft : j+1;
            }
            
            int curRight = n-1;
            for (int j=n-1; j>=0; j--) {
                right[j] = matrix[i][j] == '1' ? min(right[j], curRight) : n;
                curRight = matrix[i][j] == '1' ? curRight : j-1;
            }
            
            for (int j=0; j<n; j++)
                area = max(area, (right[j]-left[j]+1)*height[j]);
        }
        
        return area;
    }
};

以上算法参考自:

https://leetcode.com/discuss/20240/share-my-dp-solution


算法二。借鉴题目Largest Rectangle in Histogram的解法。

此题,以每行为底,都可以转换成是一个Largest Rectangle in Histogram问题。

不同的是,高度表height,需要自己算。

高度表的计算,可以用DP。已知上一行的height表,可按如下,求出本行的height值。
当矩阵当前值为1,则高度增加一个单位。否则清0.

求出height后,其他同Largest Rectangle in Histogram思路一样。

此代码在leetcode上实际执行时间为31ms。

class Solution {
public:
    int maximalRectangle(vector<vector<char> > &matrix) {
        if (matrix.empty() || matrix[0].empty())
            return 0;
        
        int area = 0;    
        const int m = matrix.size();
        const int n = matrix[0].size();
        vector<int> height(n+1);
        
        for (int i=0; i<m; i++) {
            stack<int> s;
            bool flag = true;
            for (int j=0; j<=n;) {
                if (flag && j!=n) {
                    height[j] = matrix[i][j]=='1' ? height[j]+1 : 0;
                    flag = false;
                }
                
                if (s.empty() || height[j] >= height[s.top()]) {
                    s.push(j++);
                    flag = true;
                }
                else {
                    const int altitude = height[s.top()];
                    s.pop();
                    const int left = s.empty() ? 0 : s.top()+1;
                    area = max(area, (j-left) * altitude);
                }
            }
        }
        
        return area;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值