从左到右依次遍历型

1 要观察出正方形的边长取决于三个因素,上边,左边,对角线的正方形边长的最小值,写出动态规划方程是关键,注意matrix里面的数据类型是字符串,不是数字0 1,所以不能直接用if判断,用if只要字符串不空就为真,

221. 最大正方形

2 同上一题,容易观察出以dp[i][j]为右下端点的最大正方形的边长也是其正方形的个数,

1277. 统计全为 1 的正方形子矩阵

3 这个题无论用什么动态规划方法都要从四个方向遍历四次,每个位置的最大值是四个方向中的最小值,最后再求最大值,对于数组查找不方便时,可以先将其变为集合,注意set内的元素必须是不可变对象,所以不能是数组,要把数组变为tuple再放入set中,或者可以直接建一个二维数组来记录0 1

764. 最大加号标志

下面是非常相似的一类题型,都是处理两个字符串的问题,定义dp的时候行和列长度都要加1,因为要做初始化,状态转移方程不好写时可以举例子来写,注意初始化加了一列一行后,后面遍历时的索引是从1到row+1和从1到col+1,

4 高频面试题,和编辑距离类似,关键是写出状态转移方程,子序列问题往往可以用动态规划,这个题可以用两个数组互相赋值记录数据来降低空间复杂度,

dp[i][j]= dp[i−1][j−1]+1     s1[i]==s2[j]
max(dp[i−1][j],dp[i][j−1])   s1[i]!= s2[j]​

1143. 最长公共子序列

和最长公共子序列实际上是同一个题,

1035. 不相交的线

思路同上,dp[i][j]为公共子序列的最大和,先求出所有字符的和,再减去公共的字符之和乘2,或者可以直接定义dp[i][j]为最小的删除和,只不过初始化的时候不为0,下面为计算最大公共子序列字符之和的动态转移方程:

dp[i][j]=dp[i−1][j−1] + ord(s1[col-1])          如果当前字符相等

dp[row][col] = max(dp[row-1][col], dp[row][col-1])  如果当前字符不相等
或者直接定义dp[i][j]为 s1[i-1]  s2[j-1]相等时最小的删除和,所以初始化的时候,由空字符到对应的字符要想相同要全部删除,
class Solution:
    def minimumDeleteSum(self, s1: str, s2: str) -> int:
        l1 = len(s1)
        l2 = len(s2)
        dp = [[0] * (l1+1) for _ in range(l2+1)]
        for i in range(1, l1+1):
            dp[0][i] += (dp[0][i-1]+ord(s1[i-1]))
        for i in range(1, l2+1):
            dp[i][0] += (dp[i-1][0]+ord(s2[i-1]))
        for col in range(1, l1+1):
            for row in range(1, l2+1):
                if s1[col-1] == s2[row-1]:
                    dp[row][col] = dp[row-1][col-1]
                else:
                    dp[row][col] = min(dp[row][col-1]+ord(s1[col-1]), dp[row-1][col]+ord(s2[row-1]))
        return dp[-1][-1]
View Code

相关文章: