221. 最大正方形
在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。
解:
写了暴力解的优化版本,写完之后看了题解才发现还有DP解。。。
暴力解: 遍历二维数组,以每个为1的元素作为左上顶点,从1开始依次扩充作为正方形的边长,并且正方形内每个元素判断是否为1。也就是要遍历4层。
优化版本:
- 预处理生成两个二维数组grid,grid2。
- 其含义分别为:grid[i][j]是第i行第j个元素,从左往右数连续几个1。grid2[i][j]是第i行第j个元素从上往下数连续几个1。
- 有了预处理数组之后,在暴力解选定左上顶点之后,在预处理数组中找到这个顶点往下和往右连续几个1。其中较小的值是正方形边长的第一个瓶颈。
- 假设matrix[i][j]这个元素往右连续3个1,往下连续4个1。那么边长瓶颈就是3,所以从这个顶点开始往右遍历3格,查询每个点往下能有几个1。
- 查询的过程中,记录其中每个点往下连续几个1的最小值,这是第二个瓶颈。
- 假设第二个点往下只有连续1个1,那么不需要再往后遍历了,后面不可能形成正方形。
- 没有遇到瓶颈的时候就计算一次面积,从左到右遍历完之后计算一次全局最大面积
const maximalSquare = function(matrix) {
const y = matrix.length
const x = matrix[0].length
let maxArea = 0
// 生成预处理数组
const { grid, grid2 } = preHandle()
// 遍历每个元素当做左上顶点
for (let i = 0; i < y; i++) {
for (let j = 0; j < x; j++) {
// 看这个顶点的第一个瓶颈,即顶点可能以该长度作为边长
const len = Math.min(grid[i][j], grid2[i][j])
if (matrix[i][j] !== '1' || !len) continue
const bigOne = grid[i][j] > grid2[i][j] ? grid : grid2
const smallOne = bigOne === grid ? grid2 : grid
// 当前面积
let tempArea = 0
// 第二个瓶颈,即边长上的元素最少连续几个1
let bottleneck = Infinity
// 依次查看是否满足正方形条件
for (let k = 0; k < len; k++) {
// 如果瓶颈是x轴方向,那么就依次查看沿着x轴方向上每个元素连续几个1
const targetLen = smallOne === grid ? grid2[i][j + k] : grid[i + k][j]
// 如果遇到第二个瓶颈,往后不再能形成正方形跳出循环
if (k + 1 > bottleneck) break
// 设置瓶颈
bottleneck = Math.min(targetLen, bottleneck)
// 如果没遇到瓶颈,那么k+1是可以作为正方形边长的,计算一次长度
if (targetLen >= k + 1) {
tempArea = (k + 1) ** 2
}
}
// 设置全局最大面积
maxArea = Math.max(tempArea, maxArea)
}
}
return maxArea
function preHandle () {
const grid = []
const grid2 = []
for (let i = 0; i < y; i++) {
grid[i] = []
grid2[i] = []
}
for (let i = 0; i < y; i++) {
grid[i][x - 1] = matrix[i][x - 1] === '1' ? 1 : 0
}
for (let i = 0; i < x; i++) {
grid2[y - 1][i] = matrix[y - 1][i] === '1' ? 1: 0
}
for (let i = y - 1; i >= 0; i--) {
for (let j = x - 2; j >= 0; j--) {
grid[i][j] = matrix[i][j] === '1' ? grid[i][j + 1] + 1 : 0
}
}
for (let i = y - 2; i >= 0; i--) {
for (let j = x - 1; j >= 0; j--) {
grid2[i][j] = matrix[i][j] === '1' ? grid2[i + 1][j] + 1 : 0
}
}
return { grid, grid2 }
}
};