给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
例:
输入: "sea", "eat" 输出: 2 解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
# 解析:动态规划,dp数组,一个字符串一维,向右走一格相当于增加一位对word2的字符判断,像下走一格相当于增加一位对word1的字符判断,像右下角走一格相当于各自增加一个字符的判断。如图:
word数组和dp数组下标相差一位。上边界和左边界由于没有字符可以和他们配对,所以每增加一个字符,就会需要多删除一个,所以就是顺序相加。相同时直接继承左上的值即可,即虽然各自增加了一位字符,但是dp值不变,毕竟相等,不需要进行删除操作。而不相同时,你可以选择删除其中一个,或者两个都删除:
1.删除word1则继承上方的dp值(dp[i-1][j])并且加一(因为做了删除操作);
2.删除word2则继承左边的dp值(dp[i][j-1])并且加一;
3.如果都删除则继承左上的dp值(dp[i-1][j-1])并且加二(因为同时删除了两个字符)。
然后判断这三种情况哪一种删除操作最少即可。
class Solution(object):
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1)] # 初始化dp数组
for i in range(len(word1)+1):
dp[i][0] = 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] # 则直接继承左上dp值
else: # 不相等
dp[i][j] = min(dp[i-1][j-1] + 2, dp[i-1][j] + 1, dp[i][j-1] + 1) # 三种情况三选一
return dp[-1][-1] # 返回最后的dp值