題源
出現的問題:
- 沒有正確地理解和應用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