[LeetCode]Maximal Rectangle

Maximal Rectangle

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.数组

分析

这道题是要在全部里面全为‘1’的长方形里找出最大面积那个。每每这种找最大的题目能够考虑用DP,算出全部全‘1'的长方形的面积,而后过程当中不断更新最大面积。可是这道题难点是对于一个点来讲DP表示什么,以及跟周边点DP是什么关系。spa

咱们能够这样考虑,对于一个里面所有为’1‘的长方形来讲,算其面积,最重要的几个特征是什么?有三个变量必须知道:code

1. 高度h
2. 左边界的x值x1
3. 右边界的x值x2

这样面积即为h * (x2 - x1)

因此对于矩阵中任意一点,咱们能够根据以上三个变量维护三个数组,分别为height[][], right[][], left[][],来表示以这个点为底边的任意一点,以这个点为最底向上连续’1‘的长度为轴向左向右扫,可以组成的面积最大的内部所有为’1‘的长方形。height[i][j]表示以(i, j)为底的往上最大连续’1‘的高度。left[i][j], right[i][j]表示以(i, j)点及其height[i][j]高度组成的中轴向左扩散的左边界的横坐标与向右扩散的右边界的横坐标 + 1, 扩散的要求是必须所有为’1‘。咱们能够得出如下推导公式:it

height[i][j] = matrix[i][j] == '1' ? height[i - 1][j]++ : 0;
left[i][j] = Math.max(left[i - 1][j], currLeft),currLeft表示对ith行而言,从(i,j)向左连续为'1'直至(i, currLeft)那个点;
right[i][j] = Math.min(right[i - 1][j], currRight), currRight表示ith行而言,从(i,j)向右连续为'1'直至(i, currRight - 1)那个点;;

为便于理解,见下例:io

matrix:
0 0 0 1 0 0 0 
0 0 1 1 1 0 0 
0 1 1 1 1 1 0

各点height, left及right值以下:

row 0:
h: 0 0 0 1 0 0 0
l: 0 0 0 3 0 0 0
r: 7 7 7 4 7 7 7

row 1:
h: 0 0 1 2 1 0 0
l: 0 0 2 3 2 0 0
r: 7 7 5 4 5 7 7 

row 2:
h: 0 1 2 3 3 1 0
l: 0 1 2 3 2 1 0
r: 7 6 5 4 5 6 7

注意代码实现过程当中当自己值为'0'时,咱们能够设置成left[i][j] = 0, right[i][j] = n, 并不是实际意义,只是为了下一排计算使用。虽然不是实际意义,也不影响后面面积的计算,由于height[i][j] == 0, 面积必然为0,左右边界值不影响面积计算。class

固然代码实现过程当中,因为每一个点只是与上一行有关,能够用一维数组代替二维数组。变量

复杂度

time: O(mn), space: O(n)im

代码

public class Solution {
    public int maximalRectangle(char[][] matrix) {
        int m = matrix.length;
        if (m == 0)
            return 0;
        int n = matrix[0].length;
        
        int[] height = new int[n];
        int[] left = new int[n];
        int[] right = new int[n];
        Arrays.fill(right, n); // 初始右边界为最右
        
        int max = 0;      
        for (int i = 0; i < m; i++) {
            int currLeft = 0;
            int currRight = n;
            
            // 从左到右算height及left
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == '1') {
                    height[j]++;
                    left[j] = Math.max(left[j], currLeft);
                } else {
                    height[j] = 0;
                    left[j] = 0; 
                    currLeft = j + 1;
                }
            }
            
            // 从右到左算right
            for (int j = n - 1; j >= 0; j--) {
                if (matrix[i][j] == '1') {
                    right[j] =  Math.min(right[j], currRight);
                } else {
                    right[j] = n; 
                    currRight = j;
                }
            }
                       
            for (int j = 0; j < n; j++) {
                int area = (right[j] - left[j]) * height[j];
                max = Math.max(max, area);
            }
        }
        
        return max;
    }
}
相关文章
相关标签/搜索