221. 最大正方形&&1277. 统计全为 1 的正方形子矩阵&&1504. 统计全 1 子矩形

221. 最大正方形

在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。

示例:

输入: 

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

输出: 4

dp[i][j],表示以i,j为左下角坐标的正方形的变长

dp方程:dp[i][j]=min(dp[i][j-1],dp[i-1][j],dp[i-1][j-1])+1

answer:pow(max(dp[i][j]),2)

class Solution:
    def maximalSquare(self, matrix) -> int:
        if not matrix:return 0
        m,n=len(matrix),len(matrix[0])
        dp=[[0 for _ in range(n+1)] for _ in range(m+1)]
        res=0
        for i in range(1,m+1):
            for j in range(1,n+1):
                if matrix[i-1][j-1]=='1':
                    dp[i][j]=min(dp[i][j-1],dp[i-1][j],dp[i-1][j-1])+1
                    res=max(res,dp[i][j])
        return pow(res,2)

1277. 统计全为 1 的正方形子矩阵

给你一个 m * n 的矩阵,矩阵中的元素不是 0 就是 1,请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。

 

示例 1:

输入:matrix =
[
  [0,1,1,1],
  [1,1,1,1],
  [0,1,1,1]
]
输出:15
解释: 
边长为 1 的正方形有 10 个。
边长为 2 的正方形有 4 个。
边长为 3 的正方形有 1 个。
正方形的总数 = 10 + 4 + 1 = 15.

同221题,其实dp[i][j]也可以表示这个坐标参与了多少个正方形

class Solution:
    def countSquares(self, matrix: List[List[int]]) -> int:
        #dp中每个位置的数的值代表他的左上部分最大的正方形的长度
        #同时,这个数也是他左上部分一共参与了几个三角形
        m, n = len(matrix), len(matrix[0])
        dp = [[0] * (n + 1) for _ in range(m + 1)]
        
        for i in range(1,m+1):
            for j in range(1,n+1):
                if matrix[i-1][j-1] > 0:
                    dp[i][j] = min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j]) + 1
        return sum([sum(dp[i]) for i in range(1, m+1)])

1504. 统计全 1 子矩形

给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。

 

示例 1:

输入:mat = [[1,0,1],
            [1,1,0],
            [1,1,0]]
输出:13
解释:
有 6 个 1x1 的矩形。
有 2 个 1x2 的矩形。
有 3 个 2x1 的矩形。
有 1 个 2x2 的矩形。
有 1 个 3x1 的矩形。
矩形数目总共 = 6 + 2 + 3 + 1 + 1 = 13 

class Solution:
    def numSubmat(self, mat: List[List[int]]) -> int:
        if not mat or not mat[0]: return 0
        '''
        定义二维dp[i][j], 表示第i行从(i,j)向左连续1的个数。
        对于每个(i,j),把元素(i,j)作为能组成矩阵的右下角元素,从当前行往前遍历计算结果。
        具体参见代码,时间复杂度O(n*n*m)。
        '''
        m,n=len(mat),len(mat[0])
        dp=[[0 for _ in range(n)] for _ in range(m)]
        res=0
        for i in range(m):
            for j in range(n):
                if mat[i][j]:
                    dp[i][j]= (dp[i][j-1]+1) if j>0 else 1
                    tmp=float('inf')
                    for k in range(i,-1,-1):
                        tmp=min(tmp,dp[k][j])
                        res+=tmp
                        if tmp==0:break
        return res
    

 

你可能感兴趣的:(Leetcode)