[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

你可能感兴趣的:(LeetCode)