標籤:style blog http color io 使用 ar for div
Given a 2D binary matrix filled with 0‘s and 1‘s, find the largest rectangle containing all ones and return its area.
難度:90 這是一道非常綜合的題目,要求在0-1矩陣中找出面積最大的全1矩陣。剛看到這道題會比較無從下手,brute force就是對於每個矩陣都看一下,總共有m(m+1)/2*n(n+1)/2個子矩陣(原理跟字串子串類似,字串的子串數有n(n+1)/2,只是這裡是二維情形,所以是兩個相乘),複雜度相當高,肯定不是面試官想要的答案,就不繼續想下去了。
看了一下網上的分析,發現這道題可以在Largest Rectangle in Histogram基礎之上做。假設我們把矩陣沿著某一行切下來,然後把切的行作為底面,將自底面往上的矩陣看成一個長條圖(histogram)。長條圖的中每個項的高度就是從底面行開始往上1的數量。根據Largest Rectangle in Histogram我們就可以求出當前行作為矩陣下邊緣的一個最大矩陣。接下來如果對每一行都做一次Largest Rectangle in Histogram,從其中選出最大的矩陣,那麼它就是整個矩陣中面積最大的子矩陣。
演算法的基本思路已經出來了,剩下的就是一些節省時間空間的問題了。
我們如何計算某一行為底面時長條圖的高度呢? 如果重新計算,那麼每次需要的計算數量就是當前行數乘以列數。然而在這裡我們會發現一些動態規劃的蹤跡,如果我們知道上一行長條圖的高度,我們只需要看新加進來的行(底面)上對應的列元素是不是0,如果是,則高度是0,否則則是上一行長條圖的高度加1。利用曆史資訊,我們就可以線上行時間內完成對高度的更新。我們知道,Largest Rectangle in Histogram的演算法複雜度是O(n)。所以完成對一行為底邊的矩陣求解複雜度是O(n+n)=O(n)。接下來對每一行都做一次,那麼演算法總時間複雜度是O(m*n)。
空間上,我們只需要儲存上一行長條圖的高度O(n),加上Largest Rectangle in Histogram中所使用的空間O(n),所以總空間複雜度還是O(n)。
編程上一些小細節:如果一行中左右兩相鄰元素值相等,遍曆到右邊元素(左邊元素正在棧頂),需要pop操作的,而不是push
1 public class Solution { 2 public int maximalRectangle(char[][] matrix) { 3 if (matrix==null || matrix.length==0 || matrix[0].length==0) return 0; 4 int[] height = new int[matrix[0].length]; 5 int maxArea = 0; 6 7 for (int row=0; row<matrix.length; row++) { 8 LinkedList<Integer> stack = new LinkedList<Integer>(); 9 for (int i=0; i<matrix[0].length; i++) {10 if (matrix[row][i] != ‘0‘) height[i] = height[i] + 1;11 else height[i] = 0;12 }13 for (int col=0; col<matrix[0].length; col++) {14 if (stack.size()==0 || height[col]>height[stack.peek()]) {15 stack.push(col);16 }17 else {18 int temp = stack.pop();19 int width = (stack.size()==0)? col : col-stack.peek()-1;20 maxArea = Math.max(maxArea, width*height[temp]);21 col--;22 }23 }24 while (stack.size() != 0) {25 int temp = stack.pop();26 int width = (stack.size()==0)? height.length : height.length-stack.peek()-1;27 maxArea = Math.max(maxArea, width*height[temp]);28 }29 }30 31 return maxArea;32 }33 }
Leetcode: Maximal Rectangle