85.Maximal Rectangle---dp
题目链接:https://leetcode.com/problems/maximal-rectangle/description/
题目大意:给出一个二维矩阵,计算最大的矩形面积(矩形由1组成)。例子如下:
法一:将每一行的数据都看成是一个直方图,而每个直方图的高度都是由上一行得到的,例如,上述例子中,从上到下直方图的高度依次是:[1,0,1,0,0],[2,0,2,1,1],[3,1,3,2,2],[4,0,0,3,0]。也就是当当前值是0时,则高度是0;当前值是1时,则高度=上一行的高度+1。这样,对于每一行的直方图可以利用84题的求解办法,这里多的步骤就是将每一行数据转换成直方图,然后再根据每个直方图求解最大矩形面积。代码如下(耗时49ms):
1 public int maximalRectangle(char[][] matrix) { 2 if(matrix.length == 0) { 3 return 0; 4 } 5 Stack<Integer> s = new Stack<Integer>(); 6 int h[] = new int[matrix[0].length]; 7 int res = 0; 8 for(int i = 0; i < matrix.length; i++) { 9 for(int j = 0; j < matrix[0].length; j++) { 10 //转换成直方图 11 h[j] = (matrix[i][j] == '1') ? (h[j] + 1) : 0; 12 //根据每个直方图,计算其最大矩形面积,利用84题的方法 13 while(!s.isEmpty() && h[s.peek()] >= h[j]) { 14 int cur = s.pop(); 15 res = Math.max(res, h[cur] * (s.isEmpty() ? j : (j - s.peek() - 1))); 16 } 17 s.push(j); 18 } 19 while(!s.isEmpty()) { 20 int cur = s.pop(); 21 res = Math.max(res, h[cur] * (s.isEmpty() ? h.length : (h.length - s.peek() - 1))); 22 } 23 } 24 return res; 25 }
法二:dp思想,依旧将每一行的数据看成一个直方图,然后转换成直方图,用left[]数组表示左边界1的位置,用right[]数组表示右边界1的位置。代码如下(耗时13ms):
1 public int maximalRectangle(char[][] matrix) { 2 if(matrix.length == 0) { 3 return 0; 4 } 5 int h[] = new int[matrix[0].length]; 6 int left[] = new int[matrix[0].length], right[] = new int[matrix[0].length]; 7 //初始化right数组 为matrix[0].length 8 for(int i = 0; i < matrix[0].length; i++) { 9 right[i] = matrix[0].length; 10 } 11 int res = 0; 12 for(int i = 0; i < matrix.length; i++) { 13 int cur_left = 0, cur_right = matrix[0].length; 14 //转换成直方图 15 for(int j = 0; j < matrix[0].length; j++) { 16 h[j] = (matrix[i][j] == '1') ? (h[j] + 1) : 0; 17 } 18 //计算左边1的下标 19 for(int j = 0; j < matrix[0].length; j++) { 20 if(matrix[i][j] == '1') { 21 left[j] = Math.max(left[j], cur_left); 22 } 23 else { 24 left[j] = 0; 25 cur_left = j + 1; 26 } 27 } 28 //计算右边1的下标 29 for(int j = matrix[0].length - 1; j >= 0; j--) { 30 if(matrix[i][j] == '1') { 31 right[j] = Math.min(right[j], cur_right); 32 } 33 else { 34 right[j] = matrix[0].length; 35 cur_right = j; 36 } 37 } 38 //计算矩形面积 39 for(int j = 0; j < matrix[0].length; j++) { 40 res = Math.max(res, (right[j] - left[j]) * h[j]); 41 } 42 } 43 return res; 44 }