leetcode

最大矩形(leetcode_85)

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

示例 1:

输入:matrix = [["1","0","1","0","0"],

["1","0","1","1","1"],

["1","1","1","1","1"],

["1","0","0","1","0"]]
输出:6
解释:最大矩形如上图所示。
示例 2:

输入:matrix = []
输出:0
示例 3:

输入:matrix = [["0"]]
输出:0
示例 4:

输入:matrix = [["1"]]
输出:1
示例 5:

输入:matrix = [["0","0"]]
输出:0

 

这题要结合leetcode84题来看,84题是给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。

本题我们可以扩展下,先求出矩阵中每一个“1”左边有多少个“1”,这个数字就是84题中“柱子的高度”,然后遍历矩阵的每一列,求出该列为底的情况下左边能勾勒出的矩阵的最大面积。

在84题中,我们可以思路可以类比接雨水那一题,核心思路就是找到每一个柱子两边的第一个比其矮的柱子,两者下标之差乘以该柱子的高度就是当前能构成的最大面积。

了解到基本思路后,我们在这里使用单调栈,保证栈里面的元素都是单调增加的,这样就可以在新增元素的时候,如果小于当前的栈顶,那么当前栈顶右边第一个比其小的元素就是该新增元素,此时弹出栈顶,栈中下一个元素接着比,直到找到第一个比新增元素小的,那么该新增元素的左边第一个比它小的就是该元素。我们用两个数组来存左边和右边的,左边第一个小的元素全部初始化为0,右边第一个小的全部初始化为最后一个元素。

最后算面积的时候就是遍历,每个用右边减去左边乘以高度就得到面积。

下面直接上代码:


#include <iostream>
#include <vector>
#include <stack>

using namespace std;

// class Solution
// {
// public:
//     int maximalRectangle(vector<vector<char> > &matrix)
//     {
//         int m = matrix.size();
//         if (m == 0)
//         {
//             return 0;
//         }
//         int n = matrix[0].size();
//         vector<vector<int> > left(m, vector<int>(n, 0));

//         for (int i = 0; i < m; i++)
//         {
//             for (int j = 0; j < n; j++)
//             {
//                 if (matrix[i][j] == '1')
//                     left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
//             }
//         }

//         int res = 0;
//         for (int j = 0; j < n; j++)
//         {
//             vector<int> up(m, 0), down(m, 0);
//             stack<int> stk;

//             for (int i = 0; i < m; i++)
//             {
//                 while (!stk.empty() && left[stk.top()][j] >= left[i][j])
//                 {
//                     stk.pop();
//                 }
//                 up[i] = stk.empty() ? -1 : stk.top();
//                 stk.push(i);
//             }
//             stk = stack<int>();
//             for (int i = m - 1; i >= 0; i--)
//             {
//                 while (!stk.empty() && left[stk.top()][j] >= left[i][j])
//                 {
//                     stk.pop();
//                 }
//                 down[i] = stk.empty() ? m : stk.top();
//                 stk.push(i);
//             }

//             for (int i = 0; i < m; i++)
//             {
//                 int height = down[i] - up[i] - 1;
//                 int area = height * left[i][j];
//                 res = max(res, area);
//             }
//         }
//         return res;
//     }
// };

// class Solution
// {
// public:
//     int maximalRectangle(vector<vector<char>> &matrix)
//     {
//         if (matrix.size() == 0 || matrix[0].size() == 0)
//         {
//             return 0;
//         }
//         int len = matrix[0].size() + 2, n = matrix.size(), rs = 0;
//         int high[len];
//         memset(high, 0, sizeof(high));
//         for (int row = 0; row < n; row++)
//         {
//             for (int i = 1; i < len - 1; i++)
//             {
//                 if (matrix[row][i - 1] == '0')
//                 {
//                     high[i] = 0;
//                 }
//                 else
//                 {
//                     high[i] = high[i] + 1;
//                 }
//             }
//             vector<int> hset;
//             hset.push_back(0);
//             for (int i = 1; i < len; i++)
//             {
//                 while (high[hset.back()] > high[i])
//                 {
//                     rs = max(rs, high[hset.back()] * (i - 1 - hset[hset.size() - 2]));
//                     hset.pop_back();
//                 }
//                 hset.push_back(i);
//             }
//         }
//         return rs;
//     }
// };

class Solution
{
public:
    int maximalRectangle(vector<vector<char>> &matrix)
    {
        if (matrix.empty()) return 0;

        int m = matrix.size(), n = matrix[0].size();
        int ans = 0;
        vector<vector<int> > left(m, vector<int>(n, 0));

        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (matrix[i][j] == '1')
                    left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
            }
        }

        for (int j = 0; j < n; ++j)
        {
            stack<int> stk;
            vector<int> up(m, 0), down(m, m);
            for (int i = 0; i < m; ++i)
            {
                while (!stk.empty() && left[stk.top()][j] > left[i][j])
                {
                    down[stk.top()] = i;
                    stk.pop();
                }
                up[i] = stk.empty() ? -1 : stk.top();
                stk.push(i);
            }

            for (int i = 0; i < m; i++)
            {
                ans = max(ans, left[i][j] * (down[i] - up[i] - 1));
            }
        }
        return ans;
    }
};

 

Leave a Reply

邮箱地址不会被公开。 必填项已用*标注