118. 杨辉三角
class Solution:def generate(self, numRows: int) -> List[List[int]]:dp = [[0] * i for i in range(1, numRows+1)]for i in range(numRows):for j in range(len(dp[i])):# 左右两边是1,中间部分就是其上方两个数之和if j == 0 or j == i:dp[i][j] = 1else: dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]return dp
杨辉三角其实就是利用递推思想建立的,从上一层的数值得到下一层数值。因此可以利用动态规划,每层最左边和右边的元素都是1,而中间的元素由上一层的两个元素求和得到。
119. 杨辉三角 II
class Solution:def getRow(self, rowIndex: int) -> List[int]:dp = [[0] * i for i in range(1, rowIndex+2)]for i in range(rowIndex+1):for j in range(len(dp[i])):# 左右两边是1,中间部分就是其上方两个数之和if j == 0 or j == i:dp[i][j] = 1else: dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]return dp[-1]
与上一题一样,只是要求单层的元素而已。
1277. 统计全为 1 的正方形子矩阵
class Solution:def countSquares(self, matrix: List[List[int]]) -> int:m, n = len(matrix), len(matrix[0])dp = [[0] * n for _ in range(m)]ans = 0for i in range(m):for j in range(n):if i == 0 or j == 0:dp[i][j] = matrix[i][j]elif matrix[i][j] == 0:dp[i][j] = 0else:dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1ans += dp[i][j]return ans
思路是用 dp[i][j] 表示以 (i, j) 为右下角的正方形的最大边长,然后用动态规划得到所有位置的值,过程中用 ans 记录所有边长的总数(即为正方形子矩阵的总数)。关键是求出状态转移方程,求法见官方题解。
221. 最大正方形
class Solution:def maximalSquare(self, matrix: List[List[str]]) -> int:m, n = len(matrix), len(matrix[0])dp = [[0] * n for _ in range(m)]ans = 0for i in range(m):for j in range(n):if i == 0 or j == 0:dp[i][j] = int(matrix[i][j])elif int(matrix[i][j]) == 0:dp[i][j] = 0else:dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1if dp[i][j] > ans:ans = dp[i][j]return ans ** 2
与上一题类似,这里只需要记录最大的正方形边长,则最大的正方形面积就是边长求平方。