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
解法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了,但是状态不好又把自己绕进去,哎。