学习资料:https://programmercarl.com/0115.不同的子序列.html#算法公开课
动态规划系列之编辑距离问题
学习记录:
115.不同的子序列(当遇到相同字母时,可以选择也可以不选;刚开始没看懂;dp[i][j]是对应i-1结尾和j-1结尾,这样的目的是方便第一行和第一列初始化)
点击查看代码
class Solution(object):def numDistinct(self, s, t):""":type s: str:type t: str:rtype: int"""# 动态规划解法# dp[i][j]表示以j-1为结尾的t片段和以i-1为结尾的s片段,前者作为后者的子序列的情况数量dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]# 初始化 dp[i][0], dp[0][j], dp[0][0]for i in range(len(s)):dp[i][0] = 1 # j-1=-1,那此时t片段是空字符串,这个就是t片段的子序列# 特别的,这里设定了,dp[0][0] = 1,下面要避开for j in range(1, len(t)+1):dp[0][j] = 0 # i-1 =-1,那此时t片段不为空,而s片段是空字符串,那肯定不是后者的子序列# 开始遍历for i in range(1, len(s)+1):for j in range(1, len(t)+1):if s[i-1] == t[j-1]:dp[i][j] = dp[i-1][j-1] + dp[i-1][j] # 就算相同,也有可能用,也可能不用,那两种情况都要加上else:dp[i][j] = dp[i-1][j]return dp[-1][-1]
583.两个字符串的删除操作(遇到不同字母就要删除,可以从左上角也可以从左边或者上边执行删除操作;解法二:找公共子序列,根据两字符串长度和公共子序列长度,计算最少操作数)
点击查看代码
class Solution(object):def minDistance(self, word1, word2):""":type word1: str:type word2: str:rtype: int"""# 解法一:当word1的某个字符和word2某个字符不同时,可以删除其中一个;最终删除个数就是最小步数# 动态规划,dp[i][j]代表要使得word1的前i-1和word2的前j-1相同,要删除的最小步数# 构造二维dp数组dp = [[0]*(len(word2)+1) for _ in range(len(word1)+1)]# 初始化for i in range(len(word1)+1):dp[i][0] = i # 相当于要一个i-1为结尾的word1片段与空字符串一样,那就得删除从0到i-1就是i个数for j in range(len(word2)+1):dp[0][j] = j# 开始遍历for i in range(1, len(word1)+1):for j in range(1, len(word2)+1):# 判断依据if word1[i-1] == word2[j-1]:# 递推公式dp[i][j] = dp[i-1][j-1] # 相同那就啥都不用删除,操作次数跟左上角的一样else:# 不同,就要删除一次;比如i-1,j-1的可以从左边i,j-1删除i-1这个元素dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+2)return dp[-1][-1]# 解法二:找到word1和word2的公共子序列,最小步数=len(word1)+len(word2)-len(公共子序列) # 好像是?# (略)
72.编辑距离(当两字母一样,则操作上等于左上角;若两字母不同,可能执行插入、删除或者替换,这几个就是在左上角或者左边或者上边的基础上加一)
点击查看代码
class Solution(object):def minDistance(self, word1, word2):""":type word1: str:type word2: str:rtype: int"""# 用简单例子来说明插入、删除和替换# eg1. ab和a,可以前者删除b,也可以后者添加a# eg2. ab和ac,就用替换,两者中任意一个替换最后一个字母# 动态规划二维dp数组,dp[i][j]代表word1的前i-1段和word2的前j-1段要达到相同需要的最小操作数# 构造dp数组dp = [[0]*(len(word2)+1) for _ in range(len(word1)+1)]# 初始化dp数组的第一行第一列for i in range(len(word1)+1):dp[i][0] = i # word1的前i-1段删除所有字母将等于后者空字符串for j in range(1, len(word2)+1):dp[0][j] = j# 开始遍历for i in range(1, len(word1)+1):for j in range(1, len(word2)+1):# 判断条件if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]else:# 如果两者不同,那就可能用插入、删除或者替换了,选操作数最少的dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1)return dp[-1][-1]
PS:循序渐进,能一点一点理解了,卡尔这排序牛啊
今天阴转多云,开心,吃了大盘鸡、醉鸡、干锅蛙,今天太丰盛了,家里柚子又长虫眼可惜咯