Leetcode Day 39 - DP: Subsequence
115 Distinct Subsequences | 583 Delete Operation for Two Strings | 72 Edit Distance
Dynamic Programming
Diff | Problem | Python | Java |
---|---|---|---|
115 Distinct Subsequences | ✅ | ||
583 Delete Operation for Two Strings | ✅ | ||
72 Edit Distance | ✅ |
Distinct Subsequences
Given two strings s
and t
, return the number of distinct subsequences of s
which equals t
.
The test cases are generated so that the answer fits on a 32-bit
signed integer.
Example 1
1
2
3
4
5
6
7
Input: s = "rabbbit", t = "rabbit"
Output: 3
Explanation:
As shown below, there are 3 ways you can generate "rabbit" from s.
rabbbit
rabbbit
rabbbit
Example 2
1
2
3
4
5
6
7
8
9
Input: s = "babgbag", t = "bag"
Output: 5
Explanation:
As shown below, there are 5 ways you can generate "bag" from s.
babgbag
babgbag
babgbag
babgbag
babgbag
Solution
Python
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 numDistinct(self, s, t):
m, n = len(t), len(s)
# 创建 dp 数组,dp[i][j] 表示 t 的前 i 个字符在 s 的前 j 个字符中出现的次数
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 初始化 dp[0][j] 为 1,因为空字符串 t 可以在 s 的任意前缀中匹配出 1 个子序列(不选任何字符)
for j in range(n + 1):
dp[0][j] = 1
# 动态规划填表
for i in range(1, m + 1):
for j in range(1, n + 1):
if t[i - 1] == s[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1]
else:
dp[i][j] = dp[i][j - 1]
# 返回 dp[m][n],表示 t 的整个字符串在 s 中的出现次数
return dp[m][n]
Delete Operation for Two Strings
Given two strings word1
and word2
, return the minimum number of steps required to make word1
and word2
the same.
In one step, you can delete exactly one character in either string.
Example 1
1
2
3
Input: word1 = "sea", word2 = "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".
Example 2
1
2
Input: word1 = "leetcode", word2 = "etco"
Output: 4
Solution
Python
Solution 1
dp[w1][w2]
records the largest common subsequence between word1[:w1]
and word2[w2]
, and return (n1 + n2 - 2 * dp[-1][-1])
at the end to find the minimum delete operations needed.
1
2
3
4
5
6
7
8
9
10
11
12
class Solution(object):
def minDistance(self, word1, word2):
n1, n2 = len(word1), len(word2)
dp = [[0] * (n2 + 1) for _ in range(n1 + 1)]
for w1 in range(1, n1 + 1):
for w2 in range(1, n2 + 1):
dp[w1][w2] = max(dp[w1][w2 - 1], dp[w1 - 1][w2])
if dp[w1 - 1][w2 - 1] >= dp[w1][w2] and word1[w1 - 1] == word2[w2 - 1]:
dp[w1][w2] = dp[w1 - 1][w2 - 1] + 1
return(n1 + n2 - 2 * dp[-1][-1])
Solution 2
dp[w1][w2]
records the minimum delete operations needed between word1[:w1]
and word2[w2]
directly, so dp[-1][-1]
is the answer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution(object):
def minDistance(self, word1, word2):
dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1)]
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]
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]
Edit Distance
Given two strings word1
and word2
, return the minimum number of operations required to convert word1
to word2
.
You have the following three operations permitted on a word:
- Insert a character
- Delete a character
- Replace a character
Example 1
1
2
3
4
5
6
Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation:
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')
Example 2
1
2
3
4
5
6
7
8
Input: word1 = "intention", word2 = "execution"
Output: 5
Explanation:
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')
Solution
1. dp
table and its meaning
dp[i][j]
represents the minimum edit distance between word1[:i]
and word2[:j]
.
2. Recursive formula
1
2
3
4
5
6
if (word1[i - 1] == word2[j - 1])
不操作
if (word1[i - 1] != word2[j - 1])
#Delete a character
#Insert a character
#Replace a character
** Delete a character from word1
**
At state dp[i][j]
, a character deleted from word1
-> 1 more operation than state dp[i - 1=[j]
dp[i][j] = dp[i - 1][j] + 1
** Delete a character from word2
**
At state dp[i][j]
, a character deleted from word2
-> 1 more operation than state dp[i][j - 1]
dp[i][j] = dp[i][j - 1] + 1
Replace a chareacter in word1
At state dp[i][j]
, replace chareacter word1[i - 1]
so that it equals to word2[j - 1]
dp[i][j] = dp[i - 1][j - 1] + 1
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution(object):
def minDistance(self, word1, word2):
dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1)]
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]
else:
dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
return dp[-1][-1]
Reference
Leetcode-115 Distinct Subsequences: https://leetcode.com/problems/distinct-subsequences/description/. ↩︎
代码随想录-不同的子序列: https://programmercarl.com/0115.不同的子序列.html. ↩︎
Leetcode-583 Delete Operation for Two Strings: https://leetcode.com/problems/delete-operation-for-two-strings/description/. ↩︎
代码随想录-两个字符串的删除操作: https://programmercarl.com/0583.两个字符串的删除操作.html. ↩︎
Leetcode-72 Edit Distance: https://leetcode.com/problems/edit-distance/description/. ↩︎
代码随想录-编辑距离: https://programmercarl.com/0072.编辑距离.html. ↩︎