【DP】最大正方形

peterzh6發表於2024-05-04

題源
出現的問題:

  1. 沒有正確地理解和應用DP思想,一開始想著轉移dp[i-1][j-1]的方法是掃描dp[i-1][j-1]dp[i][j]中間所有多出來的矩陣格子,但是這樣時間效率太差,而且還容易寫錯
  2. 沒有正確地轉移,只考慮了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
  3. 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
                    

相關文章