(Java)leetcode-85 Maximal Rectangle(最大矩形)

2023-11-08

题目描述

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

示例:

输入:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
输出: 6

思路整理自windliang的题解——

思路1:暴力求解

遍历每个点,求以这个点为 矩阵右下角 的所有矩阵面积。如下图的两个例子,橙色是当前遍历到的点,虚线框圈出的矩阵是其中一个矩阵。
在这里插入图片描述
怎么找出这样的矩阵呢?如下图,如果我们知道了以这个点结尾的连续 1 的个数的话,问题就变得简单了。因此,我们遍历到一个点时,先求它的矩形“宽度”——以这个点结尾的连续 1 的个数,结果将保存在一个“宽度”矩阵中(下图右侧):
在这里插入图片描述
由此,在“宽度”矩阵上求该点的最大矩形面积的方法如下:

  1. 首先求出高度是 1 的矩形面积,也就是它自身的数,如图中橙色的 4,面积就是 4(宽度为4,高度为1)。

  2. 然后向上扩展一行,高度增加一,选出当前列最小的数字,作为矩阵的宽,求出面积,对应上图的矩形框(宽度为2,高度为2)。

  3. 然后继续向上扩展,重复步骤 2。

按照上边的方法,遍历所有的点,求出所有的矩阵就可以了。

时间复杂度:O(m²n):遍历整个矩阵花费m*n,嵌套往上扩展花费m。
空间复杂度:O(mn):额外的矩阵内存消耗 。

代码

// 解法1
class Solution {
	public int maximalRectangle(char[][] matrix) {
	    if (matrix.length == 0) {
	        return 0;
	    }
	    // width矩阵用于保存以当前数字结尾的连续 1 的个数
	    int[][] width = new int[matrix.length][matrix[0].length];
	    int maxArea = 0;
	    // 遍历原阵的每一行
	    for (int row = 0; row < matrix.length; row++) {
	    	// 遍历每一列
	        for (int col = 0; col < matrix[0].length; col++) {
	            // 更新width矩阵
	            // 若当前位置为1
	            if (matrix[row][col] == '1') {
	            	// 若为第1列,则width的此位置为1
	            	// 否则在左边位置的基础上+1
	            	// 直到出现0
	                if (col == 0) {
	                    width[row][col] = 1;
	                } else {
	                    width[row][col] = width[row][col - 1] + 1;
	                }
	            } else {
	                width[row][col] = 0;
	            }
	            // 记录当前列中最小的数
	            int minWidth = width[row][col];
	            // 向上扩展行
	            for (int up_row = row; up_row >= 0; up_row--) {
	            	// 高度为矩形的长
	                int height = row - up_row + 1;
	                // 更新当前列最小的数,并用最小的数作为矩形的宽
	                minWidth = Math.min(minWidth, width[up_row][col]);
	                // 更新面积
	                maxArea = Math.max(maxArea, height * minWidth);
	            }
	        }
	    }
	    return maxArea;
	}
}

执行用时:28 ms, 在所有 Java 提交中击败了6.22%的用户
内存消耗:43.2 MB, 在所有 Java 提交中击败了32.81%的用户

思路2:拆分出子问题(单调栈)

优化思路中,首先要对leetcode-84 柱状图中最大的矩形这道题做一个回顾。
我们把矩阵中的1都视为柱状图,从上往下连续的1将组成一个柱。
从上往下遍历每一行,那么每一行都将出现不同的柱状图,用一个数组heights[] 来存当前层的柱体高度,如下图,橙色部分表示当前层的柱体,并且对应当前的heights[]。
在这里插入图片描述
如此一来,求每一行对应的最大矩形面积,就相当于求当前层柱状图的最大矩形面积,这与leetcode-84 柱状图中最大的矩形其实就是同一个问题,我们可以直接使用该题的单调栈解法:
在这里插入图片描述
因此,解决本题的思路就是求出每一行对应的heights[] ,并调用84题的方法求heights[]对应的最大矩形,在整个过程中更新最大矩形面积即可。

时间复杂度:O(mn):每一行单调栈解法花费O(n),有m行。
空间复杂度:O(n):有n列,数组空间开销。

代码

// 解法2
class Solution {
	public int maximalRectangle(char[][] matrix) {
	    if (matrix.length == 0) {
	        return 0;
	    }
	    // 一维数组heights保存当前行的“柱高度”
	    int[] heights = new int[matrix[0].length];
	    int maxArea = 0;
	    // 遍历每一行
	    for (int row = 0; row < matrix.length; row++) {
	        // 遍历每一列,更新高度
	        for (int col = 0; col < matrix[0].length; col++) {
	            if (matrix[row][col] == '1') {
	                heights[col] += 1;
	            } else {
	                heights[col] = 0;
	            }
	        }
	        // 调用上一题的解法,更新最大面积
	        maxArea = Math.max(maxArea, largestRectangleArea(heights));
	    }
	    return maxArea;
	}

	// leetcode-84 柱状图中最大的矩形
    public int largestRectangleArea(int[] heights) {
        // 这里为了代码简便,在柱体数组的头和尾加了两个高度为 0 的柱体。
        int[] tmp = new int[heights.length + 2];
        System.arraycopy(heights, 0, tmp, 1, heights.length); 
        // 栈中存的是坐标
        Stack<Integer> stack = new Stack<>();
        int area = 0;
        for (int i = 0; i < tmp.length; i++) {
            // 对栈中柱体来说,栈中的下一个柱体就是其「左边第一个小于自身的柱体」;
            // 若当前柱体 i 的高度【小于】栈顶柱体的高度,说明 i 是栈顶柱体的「右边第一个小于栈顶柱体的柱体」。
            // 因此以【栈顶】柱体为高的矩形的左右宽度边界就确定了,可以计算面积
            while (!stack.isEmpty() && tmp[i] < tmp[stack.peek()]) {
            	// 计算栈顶柱的面积
                int curHeight = tmp[stack.pop()];
                area = Math.max(area, (i - stack.peek() - 1) * curHeight);   
            }
            stack.push(i);
        }

        return area;
    }
}

执行用时:10 ms, 在所有 Java 提交中击败了61.93%的用户
内存消耗:42.6 MB, 在所有 Java 提交中击败了76.56%的用户

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(Java)leetcode-85 Maximal Rectangle(最大矩形) 的相关文章

随机推荐

  • ArcgisOpr CXX0030

    这个错误我是找了好多天才找到了 AE ArcgisEngine 在用VC环境进行开发时 对license的初始化失败 并在VC的编译输出窗口中提示Could not bind to a valid ArcGIS installation 是
  • UnitTest单元测试框架解析【实用篇】

    UnitTest是展开自动化测试的基础 这个框架很重要 首先我们先自己写一个测试类 1 被测试类 Widthget py coding utf 8class Widthget def init self size 10 10 self si
  • 常用的正则表达式总结(慢慢增加中。。。)

    1 0 100 内的数字 不包含0 100 排除0 0 0 00 保留三位小数 1 9 1 2 d 1 3 0 0 9 1 2 1 9 2 0 100 内的数字包含0 100 保留三位小数 d 1 2 d 1 3 100
  • Java将jar包打成exe包

    如何获取jar包 1 如果是maven项目 2 如果是SpringBoot项目 添加maven插件 直接使用maven插件进行打包 Jar打包成exe 准备 相关的jar Exe4j应用程序 地址 https www ej technolo
  • 第三届Python数据分析职业技能比赛A题

    第三届Python数据分析职业技能比赛A题 Hello World 赛题 竞赛背景 字段说明 考核目标 任务 任务一 数据预处理 任务二 数据可视化 任务三 数据分析 任务一思路 1 2 1 3 任务二思路 2 1 2 2 2 3 任务三思
  • 禅道程序员的10条原则

    在一个阴雨的早上 我坐在桌子旁 开始想如何才能高效的工作 在我成为一个自由职业者之前 我有很长一段时间都很努力工作 但收效甚微 我在2006开始接触禅学 我马上意识到 古代的禅宗大师们几百年前早就已经知道现今的程序员应该如何工作 虽然我很讨
  • 如何通过官方渠道下载任意版本的Spring相关的jar包

    1 进入官网http spring io 2 第二步 点击PROJECTS 3 点击SPRING FRAMEWORK 4 点击上一步中GitHub图标 进入下面的页面 第五步 把第四步出现的页面往下拉 找到 Spring Framework
  • python Matplotlib画图之调整字体大小的示例

    本文来源于公众号 csdn2299 喜欢可以关注公众号 程序员学府 本篇文章主要介绍了python Matplotlib画图之调整字体大小的示例 小编觉得挺不错的 现在分享给大家 也给大家做个参考 一起跟随小编过来看看吧 一张字体调整好的示
  • 不能在slot上绑定和触发事件

    在 slot 上进行事件的监听和分发 这是不可能的 组件的 slot 由调用它的父组件提供 这意味着所有事件都应该与父组件相关联 尝试去倾听这些变化意味着你的父子组件是紧密耦合的 可以使用 parent 来操作 div div
  • 5.1广度优先遍历的递归与迭代实现;

    队列先进先出的性质 符合 广度优先遍历时 一层一层的遍历逻辑 lc102 102 二叉树的层序遍历 107 二叉树的层次遍历II 199 二叉树的右视图 637 二叉树的层平均值 429 N叉树的层序遍历 515 在每个树行中找最大值 11
  • 谭铁牛:人工智能 找风口不如找关口

    不过我们不能光打打嘴炮 如何克服困难和挑战 让人工智能帮到你的工作 你的事业呢 让我们将李开复的演讲内容 再结合一个实例 来给大家解释一下 现在 假设你是一个程序员 虽然哥也是一媒体人 但黑起自己的行业来是丝毫不会手软的 假设你现在是一家媒
  • Python库

    库名称简介 Chardet字符编码探测器 可以自动检测文本 网页 xml的编码 colorama主要用来给文本添加各种颜色 并且非常简单易用 Prettytable主要用于在终端或浏览器端构建格式化的输出 difflib Python 标准
  • openwrt添加自己的应用程序(SDK下编译模块)出现的问题

    openwrt 版本 15 05 CC 最近在openwrt里面想编写一个串口的读写程序 没想到会出现以下问题 1 编译的时候 以下为网友遇到的问题 Package helloworld is missing dependencies fo
  • GetProcAddress()方法返回NULL值的问题

    使用动态加载的方式使用动态库 loadlibrary 成功加载动态库 之后使用GetProcAddress 方法得到函数指针却返回空值 使用GetLastError 方法得到错误代码127 出现此错误的原因一般是要加载的函数名称与动态库中函
  • 外部中断原理

    外部中断 当CPU正在按主程序运行时 外部发生了紧急事件 向CPU发送中断请求来优先处理紧急事件 当CPU处理完紧急事件后再继续从主程序断开的地方运行程序 发出中断请求的源称为中断源 不同的中断源具有不同的优先级别 当CPU同时接收到多个中
  • C++实现WebSocket简单服务器

    参考链接 链接1 链接2 链接3 WebSocket简介 WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单 允许服务端主动向客户端推送数据 在WebSocket
  • javaday09面向对象---简单谈

    Java day09 面向对象 一 成员变量和局部变量的区别 局部变量是没有默认值的 还有一个是 4 内存的位置不同 5 生命周期不同 二 内存图 形参为引用类型时 继续执行 调用function 压栈执行 以前说的是数组是引用类型 现在要
  • Boost建模与仿真 1MW设计

    这里讲一下BOOST电路从建模到系统实现 为了方便DSP移植性 所以采用离散仿真加s function C代码编写的程序 Boost 电路设计 主要仿真功率为1MW的Boost电路 主回路拓扑 Boost硬件参数选型 电容C 50000uf
  • Error: Cannot find module ‘@/views/xxx‘ at webpackEmptyContext

    从开源平台上面 clone 一个vue 项目时 登陆后 一直报找不到相对应的 module 搜了很多 后面终于解决 export const loadView view gt return gt import views view 改成如下
  • (Java)leetcode-85 Maximal Rectangle(最大矩形)

    题目描述 给定一个仅包含 0 和 1 的二维二进制矩阵 找出只包含 1 的最大矩形 并返回其面积 示例 输入 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 输出 6 思路整理自windliang的题解 思路