[leetcode]Maximal Rectangle
这道题也不简单啊。
这道题是在上一题基础上的扩展。可以做到O(n^2)的。首先上一题Largest Rectangle in Histogram有O(n)的解法。
然后计算每一个位置从开始到目前有多少连续的1(假设按列算),这个可以通过O(n^2)做到,因为可以上一个加一,h[i][j-1]+1。
接下来就是遍历每行,要注意的是之前按列算,那么现在要按行遍历。
最后仍然超时!!即使我的代码和http://www.cnblogs.com/lichen782/p/leetcode_maximal_rectangle.html一样!!
后来优化一下,不用stack了,用一个数组自己模拟栈,就过了。
public class Solution { public int maximalRectangle(char[][] matrix) { int m = matrix.length; if (m == 0) return 0; int n = matrix[0].length; if (n == 0) return 0; int h[][] = new int[m][n+1]; // n+1 is for holder 0 for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (matrix[i][j] == '0') { h[i][j] = 0; } else if (i == 0) { h[i][j] = 1; } else { h[i][j] = h[i-1][j] + 1; } } } int max = 0; for (int i = 0; i < m; i++) { int tmp = maxArea(h[i]); if (tmp > max) max = tmp; } return max; } private int maxArea(int[] h) { int max = 0; int[] stack = new int[h.length]; int idx = -1; int i = 0; while (i < h.length) { if (idx == -1 || h[i] >= h[stack[idx]]) { idx++; stack[idx] = i; i++; } else { int t = stack[idx]; idx--; int tmp = h[t] * (idx == -1 ? i : (i - stack[idx] - 1)); if (tmp > max) max = tmp; } } return max; } }
问题是那个O(n)单调栈的算法很难想到,这样的话还有一个容易想到点的算法,复杂度是O(n^3)的,只是有些优化:http://blog.sina.com.cn/s/blog_411fed0c0100bw8m.html
就是按行扫计算出每个位置的高度,这时回退到问题Largest Rectangle in Histogram。然后对任何一个高度向左向右扫,得到该高度能到cover的最左和最右。优化在于利用已经计算过的左侧的l[j]计算新l[j]
一行一行的求,如果这行的第j个是1 , 这 h[j]++; 否则 h[j] = 0;
然后对求第一行到这行的最大全1矩阵。
例如这行的h值为 5 1 1 5 3 5 这最大全1矩阵的和应该为9。
求这个需要两个数组 l[], r[] 分别表示以h[j]为矩阵的高的左边界和右边界:
for(j = 0; j < m; j ++) { l[j] = j; while(l[j] > 0 && h[j] <= h[l[j] - 1]) l[j] = l[l[j] - 1]; }
5 的左边界为 0。1 的左边界为1< 5, 1 的左边界肯定在5的左边界的左边 l[j] = l[l[j]–1]
扩展阅读:http://community.topcoder.com/stat?c=problem_statement&pm=13035