• Hard | LeetCode 85. 最大矩形 | 单调栈


    85. 最大矩形

    给定一个仅包含 01 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

    示例 1:

    img
    输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
    输出:6
    解释:最大矩形如上图所示。
    

    示例 2:

    输入:matrix = []
    输出:0
    

    示例 3:

    输入:matrix = [["0"]]
    输出:0
    

    示例 4:

    输入:matrix = [["1"]]
    输出:1
    

    示例 5:

    输入:matrix = [["0","0"]]
    输出:0
    

    提示:

    • rows == matrix.length
    • cols == matrix[0].length
    • 0 <= row, cols <= 200
    • matrix[i][j]'0''1'

    解题思路

    此题和 Hard | LeetCode 84. 柱状图中最大的矩形 | 单调栈 实际上是一道题, 只不过从一维拓展到了二维上。

    这道题首选要计算出每个位置(i, j)处从左往右连续的1的数量。那么对于每一列。就成了下图所示的样子。

    fig2

    这样这道题就转化成了求柱状图中的最大的矩形。同样参考LeetCode 84题的枚举边界和单调栈的两种思路。这道题很容易写出答案。

    方法一: 柱状图最大面积

    public int maximalRectangle(char[][] matrix) {
        int m = matrix.length;
        if (m == 0) {
            return 0;
        }
        int n = matrix[0].length;
        // 新建一个二维数组
        int[][] left = new int[m][n];
    
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 计算matrix[i][j] 左侧连续的数字1的数量
                if (matrix[i][j] == '1') {
                    left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
                }
            }
        }
        // 使用枚举边界的方法, 求出柱形图的最大面积
        int ret = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == '0') {
                    continue;
                }
                // 计算以[i, j]为右下角的最大矩形,
                // 也就是说以当前的i作为起始边界
                int width = left[i][j];
                int area = width;
                // 然后遍历[0, i]的所有left值作为边界
                for (int k = i - 1; k >= 0; k--) {
                    width = Math.min(width, left[k][j]);
                    // 不断更新面积的最大值
                    area = Math.max(area, (i - k + 1) * width);
                }
                ret = Math.max(ret, area);
            }
        }
        return ret;
    }
    

    方法二: 单调栈

    public int maximalRectangle(char[][] matrix) {
        int m = matrix.length;
        if (m == 0) {
            return 0;
        }
        int n = matrix[0].length;
        int[][] left = new int[m][n];
    
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == '1') {
                    left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
                }
            }
        }
    
        int ret = 0;
        // 对于每一列,使用基于柱状图的方法
        for (int j = 0; j < n; j++) {
    
            // 分别找出上面和下面的临界点
            int[] up = new int[m];
            int[] down = new int[m];
            Arrays.fill(down, m);
            ArrayDeque<Integer> stack = new ArrayDeque<>();
            for (int i = 0; i < m; i++) {
                while (!stack.isEmpty() && left[stack.peek()][j] >= left[i][j]) {
                    down[stack.pop()] = i;
                }
                up[i] = stack.isEmpty() ? -1 : stack.peek();
                stack.push(i);
            }
    
            for (int i = 0; i < m; i++) {
                int height = down[i] - up[i] - 1;
                int area = height * left[i][j];
                ret = Math.max(ret, area);
            }
        }
        return ret;
    }
    
  • 相关阅读:
    自己常用的数据库操作语句
    我被SQL注入撞了一下腰
    分页
    reset.css
    创建对象的多种方式
    js 数组去重
    学习JS防抖【节流】
    localStorage.js
    vue 项目移动端使用淘宝自适应插件 环境配置
    Vue项目搭建
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14999324.html
Copyright © 2020-2023  润新知