首页 > 其他分享 >动态规划(二)

动态规划(二)

时间:2022-10-23 06:33:14浏览次数:41  
标签:状态 return range lenth 数组 动态 规划 dp

动态规划(二)

动态规划问题的的一般思路:

(数学归纳思想)

判别问题是否具有最有子结构

找到base case,通过状态转移关系确认每一步的状态转换,定义dp数组的含义

主要难点在于

状态转移方程的确立;dp数组的定义,怎么表达每一步的状态转换。

(如对于两个字符串的问题,首先考虑二维dp数组)

 

递归 自顶向下:确认最小规模问题的解,由原问题向下逐级分解规模,然后逐层返回答案。通常会产生大量重叠子问题,通过记录每个子问题的解优化(如备忘录)

动态规划 自底向上:与递归相反,由最小规模问题一步步向上推直到求出原问题的解。

 

编辑距离问题:

误区:纠结于字符串灵活修改插入删除忽略最优子结构特性

base case:任一数组为空

状态转移:

状态:指针的移动     选择:删除插入修改跳过

dp数组定义:【s1长度】【s2长度】  由下标记录子问题的解

 

 1 class Solution:
 2     def minDistance(self, word1: str, word2: str) -> int:
 3         s1 = len(word1) + 1
 4         s2 = len(word2) + 1
 5         dp = [[0] * s2 for _ in range(s1)]
 6         for i in range(s1):
 7             dp[i][0] = i
 8         for i in range(s2):
 9             dp[0][i] = i
10         for i in range(1, s1):
11             for j in range(1, s2):
12                 if word1[i-1] == word2[j-1]:
13                     dp[i][j] = dp[i - 1][j - 1]
14                 else:
15                     dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1)
16         return dp[s1-1][s2-1]

 

最长回文序列:

难点:dp数组的定义     遍历方向

思考怎样同过dp数组的定义能够表达状态转移方程,状态转移需要归纳思维,说白了就是如何从已知的结果推出未知的部分。

本题中,求一个数组的最长回文序列可以由 除去头尾元素 除去头(尾)元素的子数组的最长回文序列得到当前数组的解,由此启发dp数组的定义。

思考:dp数组维度和问题指针个数

数组遍历的方向要保证正确的状态转移,由已知推位置。

 1 class Solution:
 2     def longestPalindromeSubseq(self, s: str) -> int:
 3         n = len(s)
 4         dp = [[0] * n for _ in range(n)]
 5         for i in range(n - 1, -1, -1):
 6             dp[i][i] = 1
 7             for j in range(i + 1, n):
 8                 if s[i] == s[j]:
 9                     dp[i][j] = dp[i + 1][j - 1] + 2
10                 else:
11                     dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
12         return dp[0][n - 1]si

思考最长回文子序列另一思路:把字符串翻转求两字符串最长公共子序列

 

状态压缩:

如果计算dp[i][j]需要的都是dp[i][j]相邻的状态,那么就可以使用状态压缩技巧。

说白了,就是降低dp数组维度(“投影”   增加变量储存被覆盖的值),从而降低空间复杂度。缺点是往往代码可读性也会变差。

 

以最小插入次数构造回文串:

思路类似于最长回文序列,主要处理好状态转移。

 1 class Solution:
 2     def minInsertions(self, s: str) -> int:
 3         lenth = len(s)
 4         dp = dp = [[0] * (lenth + 1) for _ in range(lenth + 1)]
 5         for i in range(lenth - 1, 0, -1):
 6             for j in range(i + 1, lenth + 1):
 7                 if s[i-1] == s[j-1]:
 8                     dp[i][j] == dp[i + 1][j - 1]
 9                 else:
10                     dp[i][j] == min(dp[i + 1][j], dp[i][j - 1]) + 1
11         return dp[1][lenth]

 

动态规划之正则表达式:

思路上还是比较容易的,本质上还是字符串匹配的问题,状态转移在于通配符的选择上。

要想到的是  在这个问题当中,相比dp数组,递归函数更便于体现状态转移

 

 1 class Solution:
 2     def isMatch(self, s: str, p: str) -> bool:
 3         m, n = len(s), len(p)
 4 
 5         def matches(i: int, j: int) -> bool:
 6             if i == 0:
 7                 return False
 8             if p[j - 1] == '.':
 9                 return True
10             return s[i - 1] == p[j - 1]
11 
12         f = [[False] * (n + 1) for _ in range(m + 1)]
13         f[0][0] = True
14         for i in range(m + 1):
15             for j in range(1, n + 1):
16                 if p[j - 1] == '*':
17                     f[i][j] |= f[i][j - 2]
18                     if matches(i, j - 1):
19                         f[i][j] |= f[i - 1][j]
20                 else:
21                     if matches(i, j):
22                         f[i][j] |= f[i - 1][j - 1]
23         return f[m][n]

 

标签:状态,return,range,lenth,数组,动态,规划,dp
From: https://www.cnblogs.com/edych/p/16815325.html

相关文章

  • 动态代理
     动态代理就是通过代理类(Proxy)的代理,使接口和实现类之间不发生直接关系,而在运行期实现动态关联。 InvocationHandle类publicObjectinvoke(Objectobj,Methodm......
  • 动态规划笔记
    初识:labuladong动态规划遵循一套固定的流程:递归的暴力解法->带备忘录的递归解法->非递归的动态规划解法。动态规划算法做的就是穷举+剪枝递归算法的时间复杂度怎......
  • ABAP-选择屏幕字段动态显示和隐藏
    字段动态隐藏字段动态显示     给对应字段加上MODIFID即可SELECT-OPTIONS:S_ZSHNAM FOR  zmmt410-zbgy MODIF ID m1,             ......
  • #yyds干货盘点# 动态规划专题:斐波那契数列
    1.简述:描述大家都知道斐波那契数列,现在要求输入一个正整数n,请你输出斐波那契数列的第n项。斐波那契数列是一个满足  的数列数据范围:要求:空间复杂度 ,时间复杂度  ,本......
  • #yyds干货盘点# 动态规划专题:跳台阶
    1.简述:描述一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。数据范围:要求:时间复杂度: ,空间复杂度: 输......
  • #yyds干货盘点# 动态规划专题:跳台阶扩展问题
    1.简述:描述一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。数据范围:进阶:空间复杂度  ,时间复杂......
  • vite Ant Design Vue 动态主题
    简单记录一下。官网地址:https://www.antdv.com/docs/vue/customize-theme-cnantd全局化配置:https://www.antdv.com/components/config-provider-cn开始没懂怎么去使用,查......
  • 动态点分治(点分树)
    点分树(动态点分治)点分治的核心思想在于依据重心划分子连通块,其良好的性质保证了最多只会分治logn层。有了这一特性,便可使用各种暴力计算答案。那么我们按照分治递归的......
  • Dev-C++ 动态调试功能
    Dev动态调试今天发现了Dev还有这个功能,感觉十分神奇,于是记录一下设置要想使用动态调试,我们必须要先打开"产生调试信息"选项这是我们的页面,这是可以看到上方有一行......
  • 力扣1235(java)-规划兼职工作(困难)
    题目:你打算利用空闲时间来做兼职工作赚些零花钱。这里有 n 份兼职工作,每份工作预计从 startTime[i] 开始到 endTime[i] 结束,报酬为 profit[i]。给你一份兼职工作......