算法第五+六周_动态规划_20210110

动态规划关键点

在这里插入图片描述

DP三部曲:
a.定义子问题,b. 定义状态数组,c. 定义状态转移方程。

动态规划两个核心点:状态转移方程和边界条件
打家劫舍问题为例
在这里插入图片描述
最长公共子序列问题是通过转化为二维数组来解决的,一般需要设置第0行,第0列为全零,这样在计算dp[i][j]的时候dp[i-1][j-1]不会越界

1143. 最长公共子序列问题使用下图进行解释:
在这里插入图片描述
代码:

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m = len(text1)
        n = len(text2)
        dp= [[0]*(n+1) for _ in range(m+1)]
        for i in range(1,m+1):
            for j in range(1,n+1):
                if text1[i-1] == text2[j-1]:
                    dp[i][j] =1 +dp[i-1][j-1]
                else:
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1])
        return dp[-1][-1]	

最长子序列问题一般都是使用动态规划来解决的。

对于排列和组合问题的补充:

518. 零钱兑换 II

排列数是有序的,比如s1=[1,2,2]和s2=[2,1,2]是两种不同的结果,组合数是无序的,s1和s2就被视为同一种结果;
对于双层循环,外层是什么就会限制什么,如果外层是硬币数,那么就是限制硬币出现的顺序,即必须使用硬币k时,金额的组合数,对于零钱兑换,这是个组合的问题,我们不关心零钱的顺序,只关心零钱有没有被用到;

下面是一个比较好的题解:
爬楼梯和兑换硬币理解组合数和排列数

总结

动态规划问题的一般形式就是求极值,求解动态规划问题的核心是穷举,但是这个穷举比较特别,因为这类问题存在重复子问题,如果使用暴力穷举,效率低下,所以就需要dp table来优化枚举过程,避免不必要的计算。
动态规划题目较多,还是多刷题,多练习,才能有更好的掌握。

猜你喜欢

转载自blog.csdn.net/a18829292719/article/details/112155632
今日推荐