给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例 1:
输入: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.lengthcols == matrix[0].length1 <= row, cols <= 200matrix[i][j]为'0'或'1'
题解:
/**
* @param {character[][]} matrix
* @return {number}
*/
// 方法一:暴力法 时间复杂度:O(m^2n) 空间复杂度:O(mn)
var maximalRectangle = function (matrix) {
// 获取二进制矩阵行数
let x = matrix.length;
if (x == 0) return 0
// 获取二进制矩阵列数
let y = matrix[0].length;
// 获取二进制矩阵 每个位置填充为0
let newArr = new Array(x).fill(0).map(() => new Array(y).fill(0))
for (let i = 0; i < x; i++) {
for (let j = 0; j < y; j++) {
if (matrix[i][j] == '1') {
// 当前位置为1时 如果是第一列 默认为1
// 如果后面连续为1累加处理
newArr[i][j] = +(j == 0 ? 0 : matrix[i][j - 1]) + 1
}
}
}
// 定义面积初始值
let ret = 0
for (let i = 0; i < x; i++) {
for (let j = 0; j < y; j++) {
// 二进制矩阵位置为0跳出
if (matrix[i][j] === '0') {
continue;
}
// 获取当前位置为1的宽度,也就是当前行当前位置有几个1
let width = newArr[i][j];
let area = width;
// 循环当前行,以及上面行所包含的面积
for (let k = i - 1; k >= 0; k--) {
// 获取当前位置最小包含宽度
width = Math.min(width, newArr[k][j]);
// 最小的高度 (i - k + 1)
area = Math.max(area, (i - k + 1) * width);
}
// 获取最大值
ret = Math.max(ret, area);
}
}
return ret
};
// 方法二:单调栈 时间复杂度:O(mn) 空间复杂度:O(mn)
var maximalRectangle = function (matrix) {
let x = matrix.length;
if (x == 0) return 0;
let y = matrix[0].length
let res = 0;
// 开辟空间多添一项0 避免原高度最后一直递增 无法有机会计算
let heights = new Array(y + 1).fill(0);
for (let row = 0; row < x; row++) {
//每一层 高度会有变化:可能继续增1, 可能直接归零
for (let col = 0; col < y; col++) {
if (matrix[row][col] == '1') {
heights[col] += 1;
} else {
heights[col] = 0;
}
}// 求出每一层的 heights[] 然后传给84题的函数 更新一下最大矩形面积
res = Math.max(res, largestRectangleArea(heights));
}
return res;
};
// 84题 单调递增栈解法
let largestRectangleArea = arr => {
let stack = [], max = 0;
for (let [i, val] of arr.entries()) {
// 非单调递增不可入栈 先处理
while (stack.length && val < arr[stack.slice(-1)]) {
let h = arr[stack.pop()];
let w = stack.length > 0 ? i - stack.slice(-1) - 1 : i;
max = Math.max(max, h * w); // 更新一下max
}
// 注意栈中存放的是下标,弹出的时候才可计算出宽度
stack.push(i);
}
return max;
}
来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。