[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;
    }
}
相關文章
相關標籤/搜索