题目描述(中等)
给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
示例 1:
输入: "sea", "eat" 输出: 2 解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
说明:
- 给定单词的长度不超过500。
- 给定单词中的字符只含有小写字母。
思路分析
题目经过包装,实际就是求两个单词的最长公共子序列。因为每次只可以删除一个字符,使得 word1 和 word2 相同所需的最小步数就是word1和word2各自非公共子序列的字符数。
使用动态规划的思想,建立一个(m+1)*(n+1)的二维数组dp,其中m,n 分别是word1,和word2的字符长度。dp[i][j]表示word1的前 j 个字符和word2的前 i 个字符中最长公共子序列数目。
边界条件是dp[1][j]和dp[i][1]的值(i=0:n-1,j=0:m-1)。其中,dp[1][j]表示word2的第一个字符word2[1]和word1的第j字符[j]是否相等,如果word2[1]==word1[j],则dp[1][j]=1,否则为dp[1][j]=0;同理dp[i][1]表示word1的第一个字符word1[1]和word2的第 i 个字符是否相等,如果 word1[1]==word2[i],则 dp[i][1]=1,否则dp[i][1]=0.
状态转移方程是:对于i=1:n+1,j=1:m+1,如果 word2[i-1]==word1[j-1],则 dp[i][j]=dp[i-1][j-1]+1;如果word2[i-1] word1[j-1],则 dp[i][j]=max(dp[i-1][j],dp[i][j-1])。
函数返回值:m+n-2*dp[n][m]
代码
class Solution:
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
m,n=len(word1),len(word2)
if m==0 or n==0:
return max(m,n)
dp=[]
[dp.append([0]*(m+1)) for i in range(n+1)]
for i in range(1,n+1):
for j in range(1,m+1):
if word2[i-1]==word1[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
return m+n-2*dp[n][m]