一、栈
承接Leetcode 84,柱状图算最大矩形面积,把该题入参改为柱状图高度即可
PS:这版本手搓int[]做栈和直接用ArrayDeque做栈,结果仅差2ms;但题84相差近15ms。
image.png
image.png

    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0) {
            return 0;
        }
        int a = matrix[0].length; // row
        int b = matrix.length;
        int[] heights = new int[a + 2];
        heights[0] = -1;
        heights[b + 1] = -1;
        int max = 0;
        for (int j = 0; j < b; j++) {
            // 构建柱状图heights
            for (int i = 0; i < a; i++) {
                boolean isZero = matrix[j][i] == '0';
                heights[i + 1] = isZero ? 0 : heights[i + 1] + 1;
            }
            max = Math.max(max, largestRectangleArea(heights));
        }
        return max;
    }

    // 参考leetcode84题解
    public int largestRectangleArea(int[] heights) {
        int max = 0;
        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(0);
        for (int i = 1; i < heights.length; i++) {
            int curH = heights[i];
            while (curH < heights[stack.peek()]) {
                int confirmIdx = stack.pop();
                max = Math.max(max, heights[confirmIdx] * (i - stack.peek() - 1));
            }
            stack.push(i);
        }
        return max;
    }

二、dp + 剪枝
image.png
自己想的第一版,记录一下。想法就是如何用到dp,那就是左边这个点,和上面这个点 ==> 当前这个点。
dp存的是所有可能最大矩形的左上角点的合集。
分五种情况讨论
左为null,上为null => 自己
左为null,上不为null => 上的最高点
左不为null,上为null => 左的最左点
左不为null,上不为null,左上为null => 上的最高点 + 左的最做点
左不为null,上不为null,左上不为null =>

  • 看左边所有的点,取其y值与上的最高点的最小值(因为左边所有点是从最左点遍历的,因此一旦其y值<=最高点的最小值,即可剪枝)
  • 若左边所有点的y值都小于最高点,则+上的最高点(否则就已经涵盖,不需要另外再加,算是剪枝的一部分)
class Solution {
    public int maximalRectangle(char[][] matrix) {
        if (matrix.length <= 0) {
            return 0;
        }
        int aSize = matrix[0].length;
        int bSize = matrix.length;
        Batch[] first = new Batch[aSize + 1];
        Batch[] second = new Batch[aSize + 1];
        int maxSize = 0;
        for (int j = 1; j < bSize + 1; j++) {
            for (int i = 1; i < aSize + 1; i++) {
                if (matrix[j - 1][i - 1] == '0') {
                    second[i]=null;
                    continue;
                }
                if (second[i - 1] == null && first[i] == null) {
                    second[i] = Batch.initSingle(i, j);
                } else if (second[i - 1] == null && first[i] != null) {
                    second[i] = Batch.initUp(first[i], i, j);
                } else if (second[i - 1] != null && first[i] == null) {
                    second[i] = Batch.initLeft(second[i - 1], i, j);
                } else {
                    second[i] = Batch.merge(second[i - 1], first[i], first[i - 1], i, j);
                }
                maxSize = Math.max(maxSize, second[i].calSize(i, j));
            }
            for (int i = 1; i < aSize + 1; i++) {
                first[i] = second[i];
            }
        }
        return maxSize;
    }

    static class Batch {

        int minX;

        int minY;

        List<Point> list;

        public static Batch init() {
            Batch batch = new Batch();
            batch.list = new ArrayList<>();
            return batch;
        }

        public static Batch initSingle(int x, int y) {
            Batch batch = init();
            batch.list.add(Point.init(x, y));
            batch.minX = x;
            batch.minY = y;
            return batch;
        }

        public static Batch initUp(Batch other, int i, int j) {
            return initSingle(i, other.minY);
        }

        public static Batch initLeft(Batch other, int i, int j) {
            return initSingle(other.minX, j);
        }

        public static Batch merge(Batch left, Batch up, Batch leftUp, int i, int j) {
            Batch b = Batch.init();
            b.minX = left.minX;
            b.minY = up.minY;
            if (leftUp == null) {
                b.list.add(Point.init(left.minX, j));
                b.list.add(Point.init(i, up.minY));
            } else {
                int minY = up.minY;
                for (Point llp : left.list) {
                    if (minY <= llp.y) {
                        b.list.add(llp);
                    } else {
                        b.list.add(Point.init(llp.x, minY));
                        break;
                    }
                }
                if (up.minY < left.minY)
                    b.list.add(Point.init(i, minY));
            }
            return b;
        }

        public int calSize(int i, int j) {
            int max = 0;
            for (Point point : list) {
                max = Math.max(point.calSize(i, j), max);
            }
            return max;
        }
    }

    static class Point {
        int x;
        int y;

        public static Point init(int x, int y) {
            Point p = new Point();
            p.x = x;
            p.y = y;
            return p;
        }

        public int calSize(int a, int b) {
            return (a - x + 1) * (b - y + 1);
        }

    }
}

lindsay_bubble
26 声望11 粉丝