【LeetCode-85】最大矩形

问题

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

解答1:前缀和(O(n*m^2))

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        if (matrix.empty()) return 0;
        int m = matrix.size(), n = matrix[0].size();
        int res = 0;
        vector<vector<int>> preSum(m + 1, vector<int>(n + 1));
        for (int i = 1; i <= m; i++) // 求前缀和
            for (int j = 1; j <= n; j++)
                if (matrix[i - 1][j - 1] == '1')
                    preSum[i][j] = preSum[i][j - 1] + 1;
        for (int i = 1; i <= m; i++) { // 以当前节点作为矩形右下角,向上遍历
            for (int j = 1; j <= n; j++) {
                int w = preSum[i][j], cur_h = i; // cur_h为当前高度坐标
                while (preSum[cur_h][j]) {
                    w = min(w, (preSum[cur_h--][j]));
                    res = max(res, w * (i - cur_h));
                }
            }
        }
        return res;
    }
};

重点思路

首先考虑暴力方法。即以当前位置为右下角,查找满足举行的最长的长和宽。本做法为暴力解法的优化方法。首先求得每行的前缀和,则在遍历时就可以以O(1)的时间找到当前高度满足举行条件的最长宽度。
本做法为暴力法的优化。

解答2:单调栈(O(mn))

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        if (matrix.empty()) return 0;
        int m = matrix.size(), n = matrix[0].size(), res = 0;
        int presum[m + 2][n + 1]; bzero(presum, sizeof presum); // 行数设为m+2,是为了给首位填0,避免单调栈中的边界讨论
        for (int i = 1; i <= m; i++) // 前缀和同方法1
            for (int j = 1; j <= n; j++)
                if (matrix[i - 1][j - 1] == '1') presum[i][j] = presum[i][j - 1] + 1;
        for (int j = 1; j <= n; j++) {
            stack<int> s;
            for (int i = 0; i < m + 2; i++) {
                while (!s.empty() && presum[s.top()][j] > presum[i][j]) {
                    int cur = s.top(); s.pop();
                    int r = i, l = s.top();
                    int w = r - l - 1;
                    res = max(res, presum[cur][j] * w);
                }
                s.push(i);
            }
        }
        return res;
    }
};

重点思路

求出前缀和后,本题与【LeetCode-84】柱状图中最大的矩形就基本上是一道题了。只不过需要对每一列进行遍历,求出所有列的最大对应柱状图。这里需要特别注意的是需要在前缀和矩阵上下分别添加空行,避免单调栈中的边界讨论。

posted @ 2021-03-29 11:31  tmpUser  阅读(96)  评论(0)    收藏  举报