leecode/problems/221.maximal-square.md
2020-05-22 18:17:19 +08:00

128 lines
3.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 题目地址
https://leetcode.com/problems/maximal-square/
## 题目描述
```
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area.
Example:
Input:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Output: 4
```
## 思路
![221.maximal-square](../assets/problems/221.maximal-square-1.jpg)
符合直觉的做法是暴力求解处所有的正方形,逐一计算面积,然后记录最大的。这种时间复杂度很高。
我们考虑使用动态规划我们使用dp[i][j]表示以matrix[i][j]为右下角的顶点的可以组成的最大正方形的边长。
那么我们只需要计算所有的ij组合然后求出最大值即可。
我们来看下dp[i][j] 怎么推导。 首先我们要看matrix[i][j], 如果matrix[i][j]等于0那么就不用看了直接等于0。
如果matrix[i][j]等于1那么我们将matrix[[i][j]分别往上和往左进行延伸直到碰到一个0为止。
如图 dp[3][3] 的计算。 matrix[3][3]等于1我们分别往上和往左进行延伸直到碰到一个0为止上面长度为1左边为3。
dp[2][2]等于1之前已经计算好了那么其实这里的瓶颈在于三者的最小值, 即`Min(1, 1, 3)`, 也就是`1`。 那么dp[3][3] 就等于
`Min(1, 1, 3) + 1`
![221.maximal-square](../assets/problems/221.maximal-square-2.jpg)
dp[i - 1][j - 1]我们直接拿到,关键是`往上和往左进行延伸`, 最直观的做法是我们内层加一个循环去做就好了。
但是我们仔细观察一下,其实我们根本不需要这样算。 我们可以直接用dp[i - 1][j]和dp[i][j -1]。
具体就是`Min(dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]) + 1`。
![221.maximal-square](../assets/problems/221.maximal-square-3.jpg)
事实上这道题还有空间复杂度O(N)的解法其中N指的是列数。
大家可以去这个[leetcode讨论](https://leetcode.com/problems/maximal-square/discuss/61803/C%2B%2B-space-optimized-DP)看一下。
## 关键点解析
- DP
- 递归公式可以利用dp[i - 1][j]和dp[i][j -1]的计算结果,而不用重新计算
- 空间复杂度可以降低到O(n), n为列数
## 代码
代码支持PythonJavaScript
Python Code
```python
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
res = 0
m = len(matrix)
if m == 0:
return 0
n = len(matrix[0])
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 if matrix[i - 1][j - 1] == "1" else 0
res = max(res, dp[i][j])
return res ** 2
```
JavaScript Code
```js
/*
* @lc app=leetcode id=221 lang=javascript
*
* [221] Maximal Square
*/
/**
* @param {character[][]} matrix
* @return {number}
*/
var maximalSquare = function(matrix) {
if (matrix.length === 0) return 0;
const dp = [];
const rows = matrix.length;
const cols = matrix[0].length;
let max = Number.MIN_VALUE;
for (let i = 0; i < rows + 1; i++) {
if (i === 0) {
dp[i] = Array(cols + 1).fill(0);
} else {
dp[i] = [0];
}
}
for (let i = 1; i < rows + 1; i++) {
for (let j = 1; j < cols + 1; j++) {
if (matrix[i - 1][j - 1] === "1") {
dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
max = Math.max(max, dp[i][j]);
} else {
dp[i][j] = 0;
}
}
}
return max * max;
};
```
***复杂度分析***
- 时间复杂度:$O(M * N)$其中M为行数N为列数。
- 空间复杂度:$O(M * N)$其中M为行数N为列数。