ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode/最大矩形

2022-05-28 14:34:51  阅读:187  来源: 互联网

标签:最大 int mono ++ LeetCode matrix 矩形 stack left


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

1. 暴力求解

该问选择合适的暴力方式也有一定的难度,既要遍历所有可能的矩形,又要尽可能减少重复运算
可以考察以每个点为右下角的最大矩阵,即在二重循环遍历中,计算每个点所有高度的面积
这样我们就能实现通过递推的方式事先算出需要用到的值,减少重复运算
left[i][j] 为矩阵第 i 行第 j 列元素的左边连续 1 的数量,这个信息可以通过递推事先计算出来
其本质是将这部分区域矩形转换成了柱状图,再求柱状图的最大矩形面积


        //要使用暴力求解的话,遍历每一个点,要能对所有矩阵进行考察
        //可以考察以该点为右下角的最大矩阵,即在二重循环遍历中,计算每个点所有高度的面积
        //时间复杂度为O(m2n)
        //left[i][j] 为矩阵第 i 行第 j 列元素的左边连续 1 的数量,也就是矩形的宽度
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') 
                //计算第 i 行第 j 列元素的左边连续 1 的数量,方便矩形面积计算
                //本质上就是将其转换成以该点为右下边界所在区域的柱状图模型
                    left[i][j] = (j == 0 ? 0: left[i][j - 1]) + 1;
            }
        }

        int ret = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                //跳过为0的矩阵减少运算
                if (matrix[i][j] == '0') continue;
                int width = left[i][j];//记录当前宽度
                int area = width;
                for (int k = i - 1; k >= 0; k--) {//遍历所有高度
                    width = min(width, left[k][j]);//更新宽度
                    area = max(area, (i - k + 1) * width);//计算并更新该点最大面积
                }
                ret = max(ret, area);//更新所有点对应最大面积
            }
        }
        return ret;
    }
};

2. 单调栈

既然方法一的实质是转换成柱状图再对每个柱状图遍历,那可以结合之前求柱状图中最大矩形的优化方式来进一步优化

单调栈优化
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>> up(m, vector<int>(n, 0));//动态规划辅助计算
        for (int i = 0; i < m; i++) 
            for (int j = 0; j < n; j++) 
                if (matrix[i][j] == '1') 
                    up[i][j] = (i == 0 ? 0: up[i-1][j]) + 1;//转换成柱状图
        int res = INT_MIN;
        for(int i = 0; i < m; i++)
            res = max(res,largestRectangleArea(up[i]));//从上往下计算每一层作为底层的柱状图
        return res;
    }

    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        vector<int> left(n), right(n);//记录每个柱子左右,满足条件的最远下标
                                    //条件指得是第一个小于柱子高度的位置
        
        stack<int> mono_stack;//单调栈
        for (int i = 0; i < n; ++i) {//从左往右遍历找每个元素左侧满足条件最远位置

            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
                mono_stack.pop();//如果左边这个元素大于当下节点,那他是包容右边的
                //提供了当下节点构成左边矩形区域一部分
                //所以可以不用看了,直接去掉,因为它被当下节点截断了,不会再影响后面元素
                //同时要露出我们的左边界
            }
            //如果满足增序关系,那左边界就是他前一个元素
            left[i] = (mono_stack.empty() ? -1 : mono_stack.top());
            //当下节点的左边界,即是左边第一个小于它的元素,因为大的元素全部去掉了
            mono_stack.push(i);//当下节点入栈,给后面元素继续判断
        }

        mono_stack = stack<int>();//单调栈
        for (int i = n - 1; i >= 0; --i) {
            while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
                mono_stack.pop();
            }
            right[i] = (mono_stack.empty() ? n : mono_stack.top());
            mono_stack.push(i);
        }
        
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
};

标签:最大,int,mono,++,LeetCode,matrix,矩形,stack,left
来源: https://www.cnblogs.com/929code/p/16320587.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有