[LeetCode] 85. Maximal Rectangle(最大矩阵)

Description

Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.
给定一 row x cols 的二进制矩阵 matrix,矩阵每个元素都是 01,找到只包含 1 的最大子矩阵并返回它的面积。

Examples

Example 1

Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
Output: 6
Explanation: The maximal rectangle is shown in the above picture.

Example 2

Input: matrix = []
Output: 0

Example 3

Input: matrix = [["0"]]
Output: 0

Example 4

Input: matrix = [["1"]]
Output: 1

Example 5

Input: matrix = [["0","0"]]
Output: 0

Constraints

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

Solution

这题的做法与第 84 题一致,甚至可以直接套用代码。以 Example 1 为例,想象把横坐标轴放在矩阵的第一行下方,每一列从坐标轴开始连续的 1 看作『柱子』,问题直接转换成 84 题,我们只要不断下移坐标轴,更新面积的最大值即可。对于 Example 1 的矩阵,每一行对应的 height 分别为:

[1, 0, 1, 0, 0]
[2, 0, 2, 1, 1]
[3, 1, 3, 2, 2]
[4, 0, 0, 3, 0]

代码如下:

import kotlin.math.max

class Solution {
    fun maximalRectangle(matrix: Array<CharArray>): Int {
        if (matrix.isEmpty() || matrix[0].isEmpty()) {
            return 0
        }
        val colLen = matrix[0].size
        val heights = IntArray(colLen)

        var result = 0

        for (row in matrix) {
            for (i in row.indices) {
                if (row[i] == '1') {
                    heights[i]++
                } else {
                    heights[i] = 0
                }
            }
            result = max(result, largestRectangleArea(heights))
        }

        return result
    }

    private fun largestRectangleArea(heights: IntArray): Int {
        if (heights.isEmpty()) {
            return 0
        }

        val lessFromLeft = IntArray(heights.size)
        val lessFromRight = IntArray(heights.size)
        lessFromLeft[0] = -1
        lessFromRight[lessFromRight.lastIndex] = heights.size

        for (i in 1..heights.lastIndex) {
            var p = i - 1
            while (p >= 0 && heights[p] >= heights[i]) {
                p = lessFromLeft[p]
            }
            lessFromLeft[i] = p
        }

        for (i in (heights.lastIndex - 1) downTo 0) {
            var p = i + 1
            while (p < heights.size && heights[p] >= heights[i]) {
                p = lessFromRight[p]
            }
            lessFromRight[i] = p
        }

        var result = 0
        for (i in heights.indices) {
            result = max(result, heights[i] * (lessFromRight[i] - lessFromLeft[i] - 1))
        }

        return result
    }
}
原文地址:https://www.cnblogs.com/zhongju/p/14177691.html