DP专题10 - leetcode221. Maximal Square/576. Out of Boundary Paths ★

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a786150017/article/details/83999754

221. Maximal Square

题目描述

给定一个2维二进制矩阵(包含0和1),找出只包含数字1的最大正方形,并返回它的面积。

例子

Input:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Output: 4

思想
(DP)
dp[i][j]表示以当前位置(i, j)为右下角的最大面积和。
初始化:只有当前位置为‘1’,面积才可能为1
转移方程
dp[i][j]表示当前位置(i, j)是正方形的右下角,所以考虑该点的左边,上边,和左上边。
当(i, j)位置为1,考虑dp[i-1][j-1], dp[i][j-1],和dp[i-1][j]三个位置的最小值,加上1,就是dp[i][j]的当前值。
解法

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

576. Out of Boundary Paths

题目描述

m*n的网格中有一个球。每次可以把球可以移动到相邻的单元格,或穿过网格的四个边界(上/下/左/右)。 但是,你最多移动N次。求可以将球移动到网格边界的路径数目。(结果 mod 10^9+7)

例子
在这里插入图片描述

思想
dp[i][j][step]表示不超过step步的情况下,从点(i, j)到边界可能的路径数。
状态转移:等同于该点周围4个位置走kstep- 1步移动到边界的路径和。
dp[i][j][step] = dp[i-1][j][step-1] + dp[i+1][j][step-1] + dp[i][j-1][step-1] + dp[i][j+1][step-1]

(法1 - DFS)
优化 - 当前坐标没有被访问过即dp[i][j][step] == -1,才进行DFS。

(法2 - DP)
外层循环是step

扫描二维码关注公众号,回复: 4361475 查看本文章

解法1
DFS

class Solution(object):
    def findPaths(self, m, n, N, i, j):
        """
        :type m: int
        :type n: int
        :type N: int
        :type i: int
        :type j: int
        :rtype: int
        """
        mod = 1000000007
        dp = [[[-1] * (N+1) for _ in range(n)] for _ in range(m)]
        
        def dfs(i, j, step):
            if i < 0 or i >= m or j < 0 or j >= n:
                return 1
            if step == 0:
                return 0
            if dp[i][j][step] == -1:
                dp[i][j][step] = dfs(i-1, j, step-1) + dfs(i, j-1, step-1) + dfs(i+1, j, step-1) + dfs(i, j+1, step-1)
            return dp[i][j][step] % mod
        
        return dfs(i, j, N)

解法2
DP。复杂度:时间 - O(Nmn),空间 - O(Nmn)

class Solution(object):
    def findPaths(self, m, n, N, i, j):
        """
        :type m: int
        :type n: int
        :type N: int
        :type i: int
        :type j: int
        :rtype: int
        """
        mod = 1000000007
        dp = [[[0] * (N+1) for _ in range(n)] for _ in range(m)]
        
        for step in range(1, N+1):
            for r in range(m):
                for c in range(n):
                    t1 = 1 if r == 0 else dp[r-1][c][step-1]
                    t2 = 1 if r == m-1 else dp[r+1][c][step-1]
                    t3 = 1 if c == 0 else dp[r][c-1][step-1]
                    t4 = 1 if c == n-1 else dp[r][c+1][step-1]
                    dp[r][c][step] = (t1 + t2 + t3 + t4) % mod
        return dp[i][j][N]

空间优化 - O(mn))
每次循环时需要开一个新的二维数组,因为每一步开始的时候,里面的二维数组值全是0。
否则,每次都更新了dp[r][c]的值,但状态方程需要的是dp[r][c][step-1]的值。

class Solution(object):
    def findPaths(self, m, n, N, i, j):
        """
        :type m: int
        :type n: int
        :type N: int
        :type i: int
        :type j: int
        :rtype: int
        """
        mod = 1000000007
        dp = [[0] * n for _ in range(m)]
        
        for step in range(1, N+1):
            temp = [[0] * n for _ in range(m)]
            for r in range(m):
                for c in range(n):
                    t1 = 1 if r == 0 else dp[r-1][c]
                    t2 = 1 if r == m-1 else dp[r+1][c]
                    t3 = 1 if c == 0 else dp[r][c-1]
                    t4 = 1 if c == n-1 else dp[r][c+1]
                    temp[r][c] = (t1 + t2 + t3 + t4) % mod
            dp = temp
        return dp[i][j]

要点

DP的初始化边界情况,221题的状态转移方程以及576题的空间优化。感觉做了很多DP了,但是状态不好又把自己绕进去,哎。

Reference

576. Out of Boundary Paths 解题报告

猜你喜欢

转载自blog.csdn.net/a786150017/article/details/83999754