221. 最大正方形

image.png

1.暴力法,利用前缀和

关于前缀和的内容可以参考我的另一篇博客:前缀和

计算二维矩阵的前缀和的复杂度为o(nm),利用前缀和我们可以在o(1)的时间内找出子矩阵的和。所以先确定矩阵的左上,然后确定其边界,判断所在的子矩阵的和是否等于边长的平方即可。

class Solution(object):
    def maximalSquare(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        def maxSideLength(mat):
            m, n = len(mat), len(mat[0])

            sum_matrix = [[0] * (n + 1) for _ in range(m + 1)]

            for i in range(1, m + 1):
                for j in range(1, n + 1):
                    sum_matrix[i][j] = int(mat[i - 1][j - 1]) + sum_matrix[i - 1][j] + sum_matrix[i][j - 1] - \
                                       sum_matrix[i - 1][j - 1]

            return sum_matrix

        def getSubSquareArea(i0,j0,i1,j1):
            if i1<i0 or j1<j0:return 0
            one_num = sum_matrix[i1+1][j1+1]-sum_matrix[i0][j1+1]-sum_matrix[i1+1][j0]+sum_matrix[i0][j0]
            if one_num ==(i1-i0+1)*(j1-j0+1):
                return (i1-i0+1)*(j1-j0+1)
            return 0

        if not matrix:
            return 0

        ans = 0
        m, n = len(matrix), len(matrix[0])
        sum_matrix = maxSideLength(matrix)
        for i in range(m):
            for j in range(n):
                if matrix[i][j]==0:continue
                max_r = min((m-i),(n-j))
                for r in range(1,max_r+1):
                    ans = max(ans,getSubSquareArea(i,j,i+r-1,j+r-1))

        return ans
2.暴力2:使用numpy库的卷积函数

卷积核的大小选择为1~n的正方形,值全为1,然后选择卷积得到的最大值,在判断是否等于卷积核的边长的平方。

卷积的知识学过cnn的肯定很清楚了,如果没学过也没必要为了这个题看,直接看动态规划的解法即可。

import numpy as np
from scipy.signal import convolve2d
class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        if not matrix: return 0
        matrix=np.array(matrix,int)
        for i in range(1,min(matrix.shape)+1):
            if convolve2d(matrix,np.ones((i,i),int),'valid').max()<i**2:
                return (i-1)**2
        return i**2
3.动态规划

刚开始我想的是将状态dp[i,j]设置为以i,j为右下角的矩阵内最大的只包含1正方形的边长。可是状态转移方程我就找不到了,因为这样无法确定正方形到底在这个矩阵的哪里,如果他不在右下,怎么转移呢?

后来看了答案,恍然大悟。

错误:dp(i, j)表示以(i, j)为右下角的矩阵内的包含的只1的正方形的边长最大值。(无法状态转移。不确定只含1的最大正方形在哪里)
正确:dp(i, j)表示以(i, j)为右下角,且只包含1的正方形的边长最大值

状态确定队列,动态规划才能继续做,可惜我还是每次都找不对。

你以为状态确定对了,我就会做了吗?太天真。我还是不会!
我看了题解看了老半天才懂。传送地址:
全是1的正方形个数

我决定直接背状态转移方程了,放弃了。


北语张益达
6 声望4 粉丝