leetcode(221). Maximal Square

本文介绍了一个寻找二维二进制矩阵中最大全1正方形的方法。通过动态规划算法,特别是优化后的空间复杂度为O(n)的实现,文章详细阐述了递推方程的设计及其代码实现。

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)

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值