1. 程式人生 > >LeetCode 221. Maximal Square (最大正方形)

LeetCode 221. 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

Reference Answer

思路分析

有兩種方法,第一種就是對矩陣的每個位置求左上角以上所有元素的和,然後用所有可能構成的正方形的區域內進行面積計算,如果面積等於正方形邊長的平方,說明是一個正方形,然後求最大面積。

第二種方法使用DP。設這個DP[i][j]陣列為以i, j位置為右下角頂點的能夠成的最大正方形的邊長。陣列如果是第一行或者第一列,顯然dp和matrix相等。如果是其他位置,當matrix[i][j] = 1時,能夠成的正方形等於左邊、上邊、左上能夠成的正方形邊長的最小值+1.為什麼是最小值?因為只要存在一個0,那麼就沒法構成更大的正方形,這個是很保守的策略。

遞推公式如下:

  • dp[0][j] = matrix[0][j] (topmost row);
  • dp[i][0] = matrix[i][0] (leftmost column);
  • For i > 0 and j > 0: if matrix[i][j] = 0, dp[i][j] = 0; if matrix[i][j] = 1, dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1.

在這裡插入圖片描述
時間複雜度是O(N2),空間複雜度是O(N2)。

這道題開始想成用相成了依據LeetCode 200 求島嶼數量的回溯法求解了,在求解過程中,回溯策略採用從左上角開始,當發現元素為1之後,當 if row < len(matrix) - 1 and col < len(matrix[0]) - 1 and matrix[row + 1][col + 1] == '1' and matrix[row + 1][ col] == '1' and matrix[row][col + 1] == '1' 進行判定,回溯return self.dfs(matrix, row + 1, col + 1) + 1

;結果證明,這種方法不能判別:

Input: 
0 0 0 1
1 1 0 1
1 1 1 1
0 1 1 1
0 1 1 1
Output: 16 (實際應該為9)

錯誤原因正是row = 1, col =1,也滿足回溯條件,故而出錯。最後看參考答案,這道題採用動態規劃更容易做。(吃了沒判定好使用動態規劃與回溯的虧)

Input:
111
010
111
Output: 1(卻被程式判別為2,因為把左下角當做一個獨立島嶼看待了)

而當先對左上角、左下角與右上角進行設定後,依舊不滿足,因為存在

Input:
11
Output: 1(卻被程式判別為2,因為把右上角當做一個獨立島嶼看待了)

最後,放棄動態規劃,改用DFS。

Code

class Solution(object):
    def maximalSquare(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if not matrix: return 0
        M = len(matrix)
        N = len(matrix[0])
        dp = [[0] * N for _ in range(M)]
        for i in range(M):
            dp[i][0] = int(matrix[i][0])
        for j in range(N):
            dp[0][j] = int(matrix[0][j])
        for i in range(1, M):
            for j in range(1, N):
                if int(matrix[i][j]) == 1:
                    dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1
        return max(map(max, dp)) ** 2

Note:

  • 動態規劃與DFS到底用哪個要仔細琢磨清楚!
  • max(map(max, dp))的使用,因為max函式無法直接作用到矩陣 dp 上,通過一個 map 對映,將max函式對映到dp元素上,得到一個迭代物件,再外套一個max函式,得到矩陣的最大值,使用方法很巧妙,值得借鑑(也可採用np.max()函式進行直接矩陣最大值求解)。

參考資料

[1] https://blog.csdn.net/fuxuemingzhu/article/details/82992233