leetcode(221). Maximal Square

来源:互联网 发布:云通信电话软件 编辑:程序博客网 时间:2024/05/09 13:04

problem

Given a 2D binary matrix filled with 0’s and 1’s, find the largest
square containing only 1’s and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.

solution

这个问题可以使用二维dp来求解,x(i, j)表示以(i, j)为右下角的正方形的最大边长,y(i, j)表示(i, j)处向左最长的连续’1’的数目,z(i, j)表示向上最长的连续’1’的数目。这样递推方程为
x = d[(i-1, j-1)][0]
y = d[(i, j-1)][1]
z = d[(i-1, j)][2]
d[(i, j)] = (1 + min(x, y, z), y+1, z+1)
代码如下(超过10%):

class Solution(object):    def maximalSquare(self, matrix):        """        :type matrix: List[List[str]]        :rtype: int        """        m = len(matrix)        if not m:            return 0        n = len(matrix[0])        ans = 0        d = {}        for i in range(m):            if matrix[i][0] == u'1':                d[(i, 0)] = (1, 1, 1)                ans = 1            else:                d[(i, 0)] = (0, 0, 0)        for i in range(n):            if matrix[0][i] == u'1':                d[(0, i)] = (1, 1, 1)                ans = 1            else:                d[(0, i)] = (0, 0, 0)        for i in range(1, m):            for j in range(1, n):                if matrix[i][j] == u'0':                    d[(i, j)] = (0,0,0)                else:                    x = d[(i-1, j-1)][0]                    y = d[(i, j-1)][1]                    z = d[(i-1, j)][2]                    d[(i, j)] = (1 + min(x, y, z), y+1, z+1)                    ans = max(ans, 1 + min(x, y, z))        return ans**2

优化:
上面的递推公式用了向右和向左的最长距离,其实只用以(i, j)为右下角的正方形的最大边长就可以完成递推,dp(i, j)=min(dp(i1, j), dp(i1, j1), 
时间和空间复杂度为O(mn)

class Solution(object):    def maximalSquare(self, matrix):        """        :type matrix: List[List[str]]        :rtype: int        """        m = len(matrix)        if not m:            return 0        n = len(matrix[0])        ans = 0        d = {}        for i in range(m):            if matrix[i][0] == u'1':                d[(i, 0)] = 1                ans = 1            else:                d[(i, 0)] = 0        for i in range(n):            if matrix[0][i] == u'1':                d[(0, i)] = 1                ans = 1            else:                d[(0, i)] = 0        for i in range(1, m):            for j in range(1, n):                if matrix[i][j] == u'0':                    d[(i, j)] = 0                else:                    x = d[(i-1, j-1)]                    y = d[(i, j-1)]                    z = d[(i-1, j)]                    d[(i, j)] = 1 + min(x, y, z)                    ans = max(ans, 1 + min(x, y, z))        # print(d)        return ans**2

优化的dp算法

可以观察到每行只用到上一行的数据,因此我们只需要存储一行子问题的解,这样就把问题的空间复杂度降为O(n)

总结

动态规划两个关键点就是子问题形式和递推方程,这个问题主要考察递推方程的形式。