LeetCode 221. 最大正方形 (巧妙DP,公式證明推導DP)
題目描述
在一個由 0
和 1
組成的二維矩陣內,找到只包含 1
的最大正方形,並返回其面積。
動態規划\(O\left(n^{2}\right)\)
f[i, j]
表示:所有以(i,j)
為右下角的且只包含1
的正方形的邊長最大值。
如下圖,從(i,j)
沿着對角線走,可以很容易的推斷出f[i][j]
受限於f[i-1][j]
(紅色正方形)和f[i][j-1]
(黃色正方形),但是其實還受限制於f[i - 1][j - 1]
黑色正方形,如第二張圖。
數學證明:
- \(f[i][j] <= f[i - 1][j] + 1\),可以到映射到圖中看一下,黃色部分+深藍色部分假設為
f[i][j]
的正確矩形,即\(f[i][j] = f[i][j-1] + 2\),那么f[i- 1] [j]
一定可以在擴大一圈。其他\(f[i][j] <= f[i][j - 1] + 1, f[i][j] <= f[i - 1][j - 1] + 1\) 都是同樣的道理。即導出公式\[f[i][j] <= min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1 \]
如圖:
-
接下來明確思路,只需要證明下面格式即可推出
\[f[i][j] <= min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1\\ f[i][j] >= min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1\\ =>f[i][j] = min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1 \]采用反證法:
\[f[i][j] < min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) + 1\\ => f[i][j] <= min(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1]) \]與下圖矛盾
時間復雜度\(O\left(n^{2}\right)\)
空間復雜度\(O\left(n^{2}\right)\)
C++代碼
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return 0;
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n + 1, vector<int>(m + 1));
int res = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
if (matrix[i - 1][j - 1] == '1') {
f[i][j] = min(f[i - 1][j], min(f[i][j - 1], f[i - 1][j - 1])) + 1;
res = max(res, f[i][j]);
}
return res * res;
}
};