继续刷LeetCode 热题 HOT 100 的题目,并且在博客更新我的solutions。在csdn博客中我会尽量用文字解释清楚,相关Java代码大家可以前往我的个人博客jinhuaiyu.com中查看。 题目:最大矩形 给定一个仅包含 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 提示: rows == matrix.length cols == matrix[0].length 1 <= row, cols <= 200 matrix[i][j] 为 ‘0’ 或 ‘1’
solution 1:使用柱状图的优化思路 我们首先要想到怎么讨论所有可能是最大矩形的矩形(当然全部讨论也包括在内),一个简单的方法就是讨论任意两个位置作为左上角和右下角,能否组成矩形,如果能,面积是不是更大。但这样时间复杂度过高。进一步的,如果我们只讨论每个位置作为右下角,能得到的最大矩形,然后取其中最大的面积,有可能能降低一些复杂度。 一个位置作为右下角能得到的最大矩形,和它左侧有多少个连续1(包括自己得是1),以及正上方(同一列)所有位置的左侧分别有多少个连续1(包括自身)有关。 我们首先计算出矩阵的每个元素的左边连续 1的数量,使用二维数组 left 记录,其中left[i][j] 为矩阵第 i 行第 j 列元素的左边连续 1的数量。这个过程的时间复杂度为O(mn)(利用一定动态规划的思想,可以在遍历的同时计算当前位置的left,如果当前位置是0,那left肯定是0,如果当前位置是1,则left为其左侧点的left+1,每行第一个点特殊处理)。 当考察以matrix[i][j] 为右下角的矩形时,我们从下到上依次讨论该位置正上方所有位置作为右上角的情况,当讨论到matrix[k][j] 时(0<=k<=i),能得到最大的矩形宽度为left[i][j],left[i?1][j],…,left[k][j]中最小值。 如图所示,假设我们现在讨论黄色位置为右下角的情况,每个位置中的数字是其对应的left(包括自身在内左侧连续的1的个数)。向上讨论同一列的每个位置matrix[k][j]作为右上角的最大矩形,当k=i时,最大矩形高为1,宽为matrix[i][j]对应的left,即3,则最大矩形面积为3。当k=i-1时,最大矩形高位2,宽为matrix[i][j]对应的left和matrix[i-1][j]对应的left中的较小者,3比4小,所以最大矩形的宽为3,最大面积为2×3=6。依此类推直到讨论完黄色位置正上方所有位置作为右上角时的最大矩形……其实,如果在某个位置碰到0后,就没有必要再讨论更上方的位置作为右上角的情况了,因为接下来的left最小值永远是0,最大面积也是0。 对每个点重复上面的过程,可以得到全局的最大矩形。枚举每个点需要O(mn)时间复杂度,讨论每个点作为右下角时的最大矩形,需要讨论其上方所有点作为右上角的最大矩形,这个过程需要O(m)的时间复杂度。总的时间复杂度是O(m2n)。
solution 2:单调栈 我们来看讨论每个位置作为右下角时最大矩形的情况: 如图所示,画出来的绿色格子是值为1的,也就是右下角位置及其正上方所有位置对应的left的直观体现。方法1是对每行的每个位置讨论它这一列的情况(该位置正上方),我们想要降低时间复杂度,可以直接一次讨论一整列,不必要求最下方的位置作为右下角,而是这一列任意两个位置组成右上角和右下角能得到的最大矩形。 这个意思就是假设上面的图最下面一行就是整个matrix的最后一行,而有数字(表示left)的这一列是matrix 中的某一列,我们如果能讨论出这个图中最大矩形,那么只需要对每一列都画出这种图,就可以讨论出全局最大矩形。 这个问题现在就退化成了leetcode的第84题(柱状图中最大矩形),大家可以回顾一下:http://jinhuaiyu.com/leetcode-largest-rectangle-in-histogram/ 84题图(求其中最大矩形,如红色区域): 84题的柱状图是横着的,我们这里是竖着的。之前我们用单调栈解决了84题,时间复杂度为O(m),列举每一列的时间复杂度为O(n),之前求二维数组left的时间复杂度为O(mn),因此总的时间复杂度为O(mn),可以看到,相比方法1,时间复杂度降低了。 怎么用单调栈求矩阵每一列对应的柱状图中的最大矩形大家可以看看上面链接中84的解析,这道题的代码也会带有详细注释。
Finally,带有详细注释的代码放在我的个人博客http://jinhuaiyu.com/leetcode-maximal-rectangle/
|