剑指 Offer II 040. 矩阵中最大的矩形

236 阅读2分钟

给定一个由 0 和 1 组成的矩阵 matrix ,找出只包含 1 的最大矩形,并返回其面积。

注意: 此题 matrix 输入格式为一维 01 字符串数组。

示例 1:

image.png

输入: matrix = ["10100","10111","11111","10010"]
输出: 6
解释: 最大矩形如上图所示。

示例 2:

输入: matrix = []
输出: 0

示例 3:

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

示例 4:

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

示例 5:

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

题解:

/**
 * @param {string[]} matrix
 * @return {number}
 */
// 方法一:优化暴力方法
var maximalRectangle = function (matrix) {
    const m = matrix.length;
    if (m == 0) return 0
    const n = matrix[0].length;
    // 根据matrix生成二维数组
    const left = new Array(m).fill(0).map(item => new Array(n).fill(0))
    // 遍历matrix向二维数组内填充数值
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            // 判断当前为1时做本行内累加获取被行内最大矩形面积
            if (matrix[i][j] == '1') {
                left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1
            }
        }
    }
    let ans = 0;
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (matrix[i][j] === '0') {
                continue;
            }
            // 本行内最大矩形宽度
            let width = left[i][j]
            let area = width;
            // 判断当前行上一行是有可以和本行形成矩形
            for (let k = i - 1; k >= 0; k--) {
                // 本行与上一行最小宽度
                width = Math.min(width, left[k][j])
                // (i - k + 1) * width 最大高度 * 宽度
                area = Math.max(area, (i - k + 1) * width)
            }
            ans = Math.max(ans, area)
        }
    }
    return ans
};


// 方法二:单调栈
var largestRectangleArea = function (heights) {
    const stack = [-1]
    let maxArea = 0
    for (let i = 0; i < heights.length; i++) {
        // 当前柱子的高度小于位于栈顶的柱子的高度
        while (stack[stack.length - 1] != -1 && heights[stack[stack.length - 1]] >= heights[i]) {
            // 以栈顶的柱子为高度计算面积
            let height = heights[stack.pop()];
            let width = i - stack[stack.length - 1] - 1;
            maxArea = Math.max(maxArea, height * width);
        }
        stack.push(i)
    }
    // 计算末尾
    while (stack[stack.length - 1] != -1) {
        let height = heights[stack.pop()];
        let width = heights.length - stack[stack.length - 1] - 1;
        maxArea = Math.max(maxArea, height * width);
    }
    return maxArea;

}
var maximalRectangle = function (matrix) {
    if (matrix.length == 0 || matrix[0].length == 0) {
        return 0;
    }
    let heights = new Array(matrix[0].length).fill(0);
    let maxArea = 0;
    // matrix = ["10100","10111","11111","10010"]
    // heights[0] = [1, 0, 1, 0, 0]
    // heights[1] = [1, 0, 2, 1, 1]
    // heights[2] = [3, 1, 3, 2, 2]
    // heights[3] = [4, 0, 0, 3, 0]
    // 遍历 每次在上一次基础上累加 本身为0是该位置还是0 形成柱状
    for (let row of matrix) {
        for (let i = 0; i < row.length; i++) {
            if (row[i] == 0) {
                heights[i] = 0
            } else {
                heights[i]++
            }
        }
        // largestRectangleArea方法获取每一轮最大面积值
        maxArea = Math.max(maxArea, largestRectangleArea(heights))
    }
    return maxArea
}

来源:力扣(LeetCode)

链接:leetcode.cn/problems/PL…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。