85、最大矩形

  1. 示例:
  • 题解
    1. 1、暴力枚举
    2. 2、动态规划——使用柱状图的优化暴力方法
    3. 3、使用柱状图 - 栈
    4. 4、动态规划——每个点的最大高度
  • 给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

    示例:

    输入:
    [
      ["1","0","1","0","0"],
      ["1","0","1","1","1"],
      ["1","1","1","1","1"],
      ["1","0","0","1","0"]
    ]
    输出: 6
    

    题解

    1、暴力枚举

    求每一个矩形

    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0) {
            return 0;
        }
        //保存以当前数字结尾的连续 1 的个数
        int[][] width = new int[matrix.length][matrix[0].length];
        int maxArea = 0;
        //遍历每一行
        for (int row = 0; row < matrix.length; row++) {
            for (int col = 0; col < matrix[0].length; col++) {
                //更新 width
                if (matrix[row][col] == '1') {
                    if (col == 0) {
                        width[row][col] = 1;
                    } else {
                        width[row][col] = width[row][col - 1] + 1;
                    }
                } else {
                    width[row][col] = 0;
                }
                //记录所有行中最小的数
                int minWidth = width[row][col];
                //向上扩展行
                for (int up_row = row; up_row >= 0; up_row--) {
                    int height = row - up_row + 1;
                    //找最小的数作为矩阵的宽
                    minWidth = Math.min(minWidth, width[up_row][col]);
                    //更新面积
                    maxArea = Math.max(maxArea, height * minWidth);
                }
            }
        }
        return maxArea;
    }
    
    // 作者:windliang
    // 链接:https://leetcode-cn.com/problems/maximal-rectangle/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-1-8/
    

    2、动态规划——使用柱状图的优化暴力方法

    class Solution {
        public int maximalRectangle(char[][] matrix) {
            if (matrix.length == 0) return 0;
            int maxarea  = 0;
            // 动态规划
            // dp[i][j]表示宽度i-j的宽度
            int[][] dp = new int[matrix.length][matrix[0].length];
            
            for (int i = 0;i < matrix.length; i++) {
                for (int j = 0;j < matrix[0].length;j++) {
                    if (matrix[i][j] == '1'){
                        // 计算最大宽度,并更新
                        dp[i][j] = j == 0? 1 : dp[i][j-1]+1;
                        
                        int width = dp[i][j];
                        
                        // 计算最大的面积,在[i,j]较低的右下角
                        for (int k = i;k >= 0;k--) {
                            width = Math.min(width,dp[k][j]);
                            maxarea = Math.max(maxarea,width*(i-k+1));
                        }
                    }
                }
            }
            return maxarea;
        }
    }
    

    3、使用柱状图 - 栈

    迭代求最大的面积

    class Solution {
        // 84题的解:利用栈从一个柱状图中获取最大的面积
        public int leetcode84 (int [] heights) {
            Stack<Integer> stack = new Stack<>();
            stack.push(-1);
            int maxarea = 0;
            for (int i = 0;i < heights.length;i++) {
                while(stack.peek() != -1 && heights[stack.peek()] >= heights[i]) {
                    maxarea = Math.max(maxarea,heights[stack.pop()]*(i - stack.peek() - 1));
                }
                stack.push(i);
            }
            while (stack.peek() != -1) {
                maxarea = Math.max(maxarea,heights[stack.pop()]*(heights.length - stack.peek() - 1));
            }
            return maxarea;
        }
    
        // 85题的解答
        public int maximalRectangle(char[][] matrix) {
            if (matrix.length == 0) {return 0;}
            int maxarea = 0;
            // dp 存储每一行的矩形值
            int[] dp = new int[matrix[0].length];
            // 遍历每一个位置
            for (int i = 0;i < matrix.length;i++) {
                for (int j = 0;j < matrix[0].length;j++) {
                    // 滚动数组,更新当前的柱状图
                    dp[j] = matrix[i][j] == '1' ? dp[i+1] : 0;
                }
                // 求当前柱状图的最大面结
                maxarea = Math.max(maxarea,leetcode84(dp));
            }
            return maxarea;
        }
    }
    

    4、动态规划——每个点的最大高度

    public class Solution {
        public int maximalRectangle(char[][] matrix) {
            if (matrix.length == 0) { return 0; }
            int m = matrix.length;// 行数
            int n = matrix[0].length;// 列数
    
            int[] left = new int[n];// 初始值为0
            int[] right = new int[n];
            int[] height = new int[n];// 初始值为 0
    
            Arrays.fill(rigth,n);// 初始值为 n
            int maxarea = 0;
            // 对于每一列
            for (int i = 0;i < m;i++) {
                int cur_left = 0,cur_right = n;
                // 更新高度
                for (int j = 0;j < n;j++) {
                    if (martix[i][j] == '1') {
                        height[j]++;
                    } else {
                        height[j] = 0;
                    }
                }
    
                // 更新左侧
                for (int j = 0;j < n;j++) {
                    if (matrix[i][j] == '1') {
                        // 更新历史最大值
                        left[j] = Math.max(cur_left,left[j]);
                    } else {
                        left[j] = 0;
                        cur_left = j+1;
                    }
                }
                // 更新右侧
                for (int j = n - 1;j >= 0;j--) {
                    if (matrix[i][j] == '1') {
                        rigth[i] = Math.min(cur_right,rigth[i]);
                    } else {
                        right[j] = n;
                        cur_rigth = j;
                    }
                }
                // 迭代求最大的面结
                for (int j = 0;j < n;j++) {
                    maxarea = Math.max(maxarea,(right[j]-left[j]) * height[j]);
                }
            }
            return maxarea;
        }
    }
    // 规范命名
    class Solution {
        public int maximalRectangle(char[][] matrix) {
            int rows = matrix.length;
            if (rows == 0) {
                return 0;
            }
            int cols = matrix[0].length;
            int[] height = new int[cols];
            int[] left = new int[cols];
            int[] right = new int[cols];
            // 当前的左右边界值
            int farthestLeft, farthestRight;
            int maxArea = 0;
            int currentArea;
    
            Arrays.fill(right, cols);
            for (int i = 0; i < rows; i++) {
                farthestLeft = 0;
                farthestRight = cols;
                // 统计left边界
                for (int j = 0; j < cols; j++) {
                    if (matrix[i][j] == '1') {
                        left[j] = farthestLeft > left[j] ? farthestLeft : left[j];
                    }else {
                        left[j] = 0;
                        farthestLeft = j + 1;
                    }
                }
                // 统计height right 以及更新最大面积
                for (int j = cols - 1; j >= 0; j--) {
                    if (matrix[i][j] == '1') {
                        height[j]++;
                        right[j] = farthestRight < right[j] ? farthestRight : right[j];
                        currentArea = (right[j] - left[j]) * height[j];
                        maxArea = currentArea > maxArea ? currentArea : maxArea;
                    }else {
                        height[j] = 0;
                        right[j] = cols;
                        farthestRight = j;
                    }
                }
            }
    
            return maxArea;
        }
    }
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

    💰

    Title:85、最大矩形

    Count:1.2k

    Author:攀登

    Created At:2020-07-26, 00:19:44

    Updated At:2024-06-15, 15:52:32

    Url:http://jiafeimao-gjf.github.io/2020/07/26/85%E3%80%81%E6%9C%80%E5%A4%A7%E7%9F%A9%E5%BD%A2/

    Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

    ×

    Help us with donation