【DP】最大正方形
题源
出现的问题:
- 没有正确地理解和应用DP思想,一开始想着转移dp[i-1][j-1]的方法是扫描
dp[i-1][j-1]
到dp[i][j]
中间所有多出来的矩阵格子,但是这样时间效率太差,而且还容易写错 - 没有正确地转移,只考虑了
dp[i-1][j-1]
到dp[i][j]
,没有考虑dp[i-1][j]和dp[i][j-1]
,正确的思路是如果dp[i][j]
的值是 1,则dp[i][j]
的值由其上方dp[i-1][j]
、左方dp[i][j-1]
和左上方dp[i-1][j-1
的三个相邻位置的 dp 值决定。具体而言,当前位置的元素值等于三个相邻位置的元素中的最小值加 1 - 当
dp[i-1][j-1]
比dp[i-1][j]和dp[i][j-1]
大而且非零时,我原来的算法会引发灾难性的问题,简单来说就是计算多出来的格子的时候起始位置太靠前了,导致碰到了零,然后就正方形判定失败了,但其实如果用保守点的值,dp[i-1][j]和dp[i][j-1]
,的话,是没有问题的,这就是为什么需要min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])
正确解答:
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
if not matrix or not matrix[0]:
return 0
m, n = len(matrix), len(matrix[0])
max_side = 0
dp = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if matrix[i][j] == "1":
dp[i][j] = 1
max_side = max(max_side, 1)
for i in range(1, m):
for j in range(1, n):
if matrix[i][j] == "1":
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
max_side = max(max_side, dp[i][j])
return max_side * max_side
错误解答:
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
m = len(matrix)
n = len(matrix[0])
max_side = 0
dp = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
dp[i][j] = 1 if matrix[i][j] == "1" else 0
max_side = max(max_side, dp[i][j])
for i in range(m):
for j in range(n):
i_ = i - 1
j_ = j - 1
if i_ >= 0 and j_ >= 0 and dp[i_][j_] != 0 and dp[i][j] != 0:
flag = True
attemped_side = dp[i-1][j-1]
for k in range(j-attemped_side, j):
if i == 4: print(matrix[i][k])
if matrix[i][k] == "0":
flag = False
break
for k in range(i-attemped_side, i):
if j == 4: print(matrix[k][j])
if matrix[k][j] == "0":
flag = False
break
if flag == True:
dp[i][j] = dp[i_][j_] + 1
max_side = max(max_side, dp[i][j])
return max_side * max_side