1. 程式人生 > >最大的矩形面積 Maximal Rectangle

最大的矩形面積 Maximal Rectangle

htm public length for angle col ram com pub

2018-09-15 10:23:44

一、Largest Rectangle in Histogram

在求解最大的矩形面積之前,我們先討論一條最大直方圖面積的問題。

問題描述:

技術分享圖片

問題求解:

解法一、樸素解法,O(n ^ 2)。

解決的思路就是遍歷一遍,如果當前的數比後一個數要小,那麽當前的額數字肯定不可能是最大面積的右邊界,遍歷下一個數;

如果當前數比後一個大,那麽假設當前的為右邊界,向左進行遍歷,計算面積最大值。

    public int largestRectangleArea(int[] heights) {
        if (heights.length == 0) return 0;
        int res = 0;
        for (int i = 0; i < heights.length; i++) {
            if (i == heights.length - 1 || heights[i] > heights[i + 1]) {
                int minHeight = heights[i];
                for (int j = i; j >= 0; j--) {
                    minHeight = Math.min(heights[j], minHeight);
                    res = Math.max(res, minHeight * (i - j + 1));
                }
            }
        }
        return res;
    }

解法二、使用堆棧,時間復雜度O(n)。

核心的思路是,尋找每個直方圖的左邊和右邊第一個比他小的位置,然後計算其能達到的面積最大值,最後取max即可。

    public int largestRectangleArea(int[] heights) {
        if (heights.length == 0) return 0;
        int res = 0;
        Stack<Integer> stack = new Stack<>();
        int idx, leftMost, rightMost;
        for (int i = 0; i < heights.length; i++) {
            if (stack.isEmpty() || heights[i] >= heights[stack.peek()]) stack.push(i);
            else {
                rightMost = i;
                idx = stack.pop();
                while (!stack.isEmpty() && heights[stack.peek()] == heights[idx]) idx = stack.pop();
                leftMost = stack.isEmpty() ? -1 : stack.peek();
                res = Math.max(res, heights[idx] * (rightMost - leftMost - 1));
                i--;
            }
        }
        rightMost = stack.isEmpty() ? 0 :stack.peek() + 1;
        while (!stack.isEmpty()) {
            idx = stack.pop();
            leftMost = stack.isEmpty() ? -1 : stack.peek();
            res = Math.max(res, heights[idx] * (rightMost - leftMost - 1));
        }
        return res;
    }

二、Maximal Rectangle

問題描述:

技術分享圖片

問題求解:

有個上一個問題的鋪墊,這個問題就很好解決了,針對每一行,可以先求出其高度,然後再對每一行求最大最方圖的面積,取max即可。

    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0 || matrix[0].length == 0) return 0;
        int m = matrix.length;
        int n = matrix[0].length;
        int[][] height = new int[m][n];
        int res = 0;
        for (int i = 0; i < n; i++) height[0][i] = matrix[0][i] - ‘0‘;
        for (int i = 1; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == ‘0‘) height[i][j] = 0;
                else height[i][j] = 1 + height[i - 1][j];
            }
        }
        for (int i = 0; i < m; i++) {
            res = Math.max(res, fastHelper(height[i]));
        }
        return res;
    }

    private int helper(int[] nums) {
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i == nums.length - 1 || nums[i] > nums[i + 1]) {
                int minHeight = nums[i];
                for (int j = i; j >= 0; j--) {
                    minHeight = Math.min(minHeight, nums[j]);
                    res = Math.max(res, (i - j + 1) * minHeight);
                }
            }
        }
        return res;
    }

    private int fastHelper(int[] nums) {
        int res = 0;
        int idx, leftMost, rightMost;
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < nums.length; i++) {
            if (stack.isEmpty() || nums[i] >= nums[stack.peek()]) stack.push(i);
            else {
                rightMost = i;
                idx = stack.pop();
                while (!stack.isEmpty() && nums[idx] == nums[stack.peek()]) idx= stack.pop();
                leftMost = stack.isEmpty() ? -1 : stack.peek();
                res = Math.max(res, nums[idx] * (rightMost - leftMost - 1));
                i--;
            }
        }
        rightMost = stack.isEmpty() ? 0 : stack.peek() + 1;
        while (!stack.isEmpty()) {
            idx = stack.pop();
            while (!stack.isEmpty() && nums[idx] == nums[stack.peek()]) idx= stack.pop();
            leftMost = stack.isEmpty() ? -1 : stack.peek();
            res = Math.max(res, nums[idx] * (rightMost - leftMost - 1));
        }
        return res;
    }

最大的矩形面積 Maximal Rectangle