编辑距离

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
示例 1:

1
2
3
4
5
6
输入: word1 = "horse", word2 = "ros"
输出: 3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

示例 2:
1
2
3
4
5
6
7
8
输入: word1 = "intention", word2 = "execution"
输出: 5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

思路 + 代码

  • 问题1:如果 word1[0..i-1] 到 word2[0..j-1] 的变换需要消耗 k 步,那 word1[0..i] 到 word2[0..j] 的变换需要几步呢?

  • 答:先使用 k 步,把 word1[0..i-1] 变换到 word2[0..j-1],消耗 k 步。再把 word1[i] 改成 word2[j],就行了。如果 word1[i] == word2[j],什么也不用做,一共消耗 k 步,否则需要修改,一共消耗 k + 1 步。

  • 问题2:如果 word1[0..i-1] 到 word2[0..j] 的变换需要消耗 k 步,那 word1[0..i] 到 word2[0..j] 的变换需要消耗几步呢?

  • 答:先经过 k 步,把 word1[0..i-1] 变换到 word2[0..j],消耗掉 k 步,再把 word1[i] 删除,这样,word1[0..i] 就完全变成了 word2[0..j] 了。一共 k + 1 步。

  • 问题3:如果 word1[0..i] 到 word2[0..j-1] 的变换需要消耗 k 步,那 word1[0..i] 到 word2[0..j] 的变换需要消耗几步呢?

  • 答:先经过 k 步,把 word1[0..i] 变换成 word2[0..j-1],消耗掉 k 步,接下来,再插入一个字符 word2[j], word1[0..i] 就完全变成了 word2[0..j] 了。

从上面三个问题来看,word1[0..i] 变换成 word2[0..j] 主要有三种手段,用哪个消耗少,就用哪个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution(object):
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
m, n = len(word1), len(word2)
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(m+1):
dp[i][0] = i
for j in range(n+1):
dp[0][j] = j
for i in range(1, m+1):
for j in range(1, n+1):
# 如果当前的字符相等,则最小操作数与dp[i-1][j-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], min(dp[i-1][j], dp[i][j-1]))+1
return dp[m][n]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/edit-distance
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

只有两个键的键盘

最初在一个记事本上只有一个字符 ‘A’。你每次可以对这个记事本进行两种操作:

Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。
Paste (粘贴) : 你可以粘贴你上一次复制的字符。
给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 ‘A’。输出能够打印出 n 个 ‘A’ 的最少操作次数。

示例 1:

1
2
3
4
5
6
7
8
9
10
输入: 3
输出: 3
解释:
最初, 我们只有一个字符 'A'
1 步, 我们使用 Copy All 操作。
2 步, 我们使用 Paste 操作来获得 'AA'
3 步, 我们使用 Paste 操作来获得 'AAA'
说明:

n 的取值范围是 [1, 1000] 。

思路 + 代码

动态规划。例如 9 ,从数字 8 开始依次找其最大除数,例如是3.
那么dp[9] = d[3] + 9/3

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution(object):
def minSteps(self, n):
"""
:type n: int
:rtype: int
"""
dp = [0]*(n+1)
for i in range(2,n+1):
for j in range(i-1, 0, -1):
if i % j == 0:
dp[i] = dp[j] + i//j
break
return dp[n]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/2-keys-keyboard
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。