String
Dynamic Programming
Description
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:
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:
Input: word1 = "leetcode", word2 = "etco"
Output: 4
Constraints:
1 <= word1.length, word2.length <= 500
word1
and word2
consist of only lowercase English letters.
Solutions
Solution 1: Dynamic Programming
We define $f[i][j]$ as the minimum number of deletions required to make the first $i$ characters of the string $\textit{word1}$ and the first $j$ characters of the string $\textit{word2}$ the same. The answer is $f[m][n]$, where $m$ and $n$ are the lengths of the strings $\textit{word1}$ and $\textit{word2}$, respectively.
Initially, if $j = 0$, then $f[i][0] = i$; if $i = 0$, then $f[0][j] = j$.
When $i, j > 0$, if $\textit{word1}[i - 1] = \textit{word2}[j - 1]$, then $f[i][j] = f[i - 1][j - 1]$; otherwise, $f[i][j] = \min(f[i - 1][j], f[i][j - 1]) + 1$.
Finally, return $f[m][n]$.
The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the lengths of the strings $\textit{word1}$ and $\textit{word2}$, respectively.
Python3 Java C++ Go TypeScript Rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 class Solution :
def minDistance ( self , word1 : str , word2 : str ) -> int :
m , n = len ( word1 ), len ( word2 )
f = [[ 0 ] * ( n + 1 ) for _ in range ( m + 1 )]
for i in range ( 1 , m + 1 ):
f [ i ][ 0 ] = i
for j in range ( 1 , n + 1 ):
f [ 0 ][ j ] = j
for i , a in enumerate ( word1 , 1 ):
for j , b in enumerate ( word2 , 1 ):
if a == b :
f [ i ][ j ] = f [ i - 1 ][ j - 1 ]
else :
f [ i ][ j ] = min ( f [ i - 1 ][ j ], f [ i ][ j - 1 ]) + 1
return f [ m ][ n ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 class Solution {
public int minDistance ( String word1 , String word2 ) {
int m = word1 . length (), n = word2 . length ();
int [][] f = new int [ m + 1 ][ n + 1 ] ;
for ( int i = 0 ; i <= m ; ++ i ) {
f [ i ][ 0 ] = i ;
}
for ( int j = 0 ; j <= n ; ++ j ) {
f [ 0 ][ j ] = j ;
}
for ( int i = 1 ; i <= m ; ++ i ) {
for ( int j = 1 ; j <= n ; ++ j ) {
char a = word1 . charAt ( i - 1 );
char b = word2 . charAt ( j - 1 );
if ( a == b ) {
f [ i ][ j ] = f [ i - 1 ][ j - 1 ] ;
} else {
f [ i ][ j ] = Math . min ( f [ i - 1 ][ j ] , f [ i ][ j - 1 ] ) + 1 ;
}
}
}
return f [ m ][ n ] ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 class Solution {
public :
int minDistance ( string word1 , string word2 ) {
int m = word1 . length (), n = word2 . length ();
vector < vector < int >> f ( m + 1 , vector < int > ( n + 1 ));
for ( int i = 0 ; i <= m ; ++ i ) {
f [ i ][ 0 ] = i ;
}
for ( int j = 0 ; j <= n ; ++ j ) {
f [ 0 ][ j ] = j ;
}
for ( int i = 1 ; i <= m ; ++ i ) {
for ( int j = 1 ; j <= n ; ++ j ) {
char a = word1 [ i - 1 ];
char b = word2 [ j - 1 ];
if ( a == b ) {
f [ i ][ j ] = f [ i - 1 ][ j - 1 ];
} else {
f [ i ][ j ] = min ( f [ i - 1 ][ j ], f [ i ][ j - 1 ]) + 1 ;
}
}
}
return f [ m ][ n ];
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 func minDistance ( word1 string , word2 string ) int {
m , n := len ( word1 ), len ( word2 )
f := make ([][] int , m + 1 )
for i := range f {
f [ i ] = make ([] int , n + 1 )
f [ i ][ 0 ] = i
}
for j := 1 ; j <= n ; j ++ {
f [ 0 ][ j ] = j
}
for i := 1 ; i <= m ; i ++ {
for j := 1 ; j <= n ; j ++ {
a , b := word1 [ i - 1 ], word2 [ j - 1 ]
if a == b {
f [ i ][ j ] = f [ i - 1 ][ j - 1 ]
} else {
f [ i ][ j ] = 1 + min ( f [ i - 1 ][ j ], f [ i ][ j - 1 ])
}
}
}
return f [ m ][ n ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 function minDistance ( word1 : string , word2 : string ) : number {
const m = word1 . length ;
const n = word2 . length ;
const f : number [][] = Array . from ({ length : m + 1 }, () => Array ( n + 1 ). fill ( 0 ));
for ( let i = 1 ; i <= m ; ++ i ) {
f [ i ][ 0 ] = i ;
}
for ( let j = 1 ; j <= n ; ++ j ) {
f [ 0 ][ j ] = j ;
}
for ( let i = 1 ; i <= m ; ++ i ) {
for ( let j = 1 ; j <= n ; ++ j ) {
if ( word1 [ i - 1 ] === word2 [ j - 1 ]) {
f [ i ][ j ] = f [ i - 1 ][ j - 1 ];
} else {
f [ i ][ j ] = Math . min ( f [ i - 1 ][ j ], f [ i ][ j - 1 ]) + 1 ;
}
}
}
return f [ m ][ n ];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 impl Solution {
pub fn min_distance ( word1 : String , word2 : String ) -> i32 {
let m = word1 . len ();
let n = word2 . len ();
let s : Vec < char > = word1 . chars (). collect ();
let t : Vec < char > = word2 . chars (). collect ();
let mut f = vec! [ vec! [ 0 ; n + 1 ]; m + 1 ];
for i in 0 ..= m {
f [ i ][ 0 ] = i as i32 ;
}
for j in 0 ..= n {
f [ 0 ][ j ] = j as i32 ;
}
for i in 1 ..= m {
for j in 1 ..= n {
let a = s [ i - 1 ];
let b = t [ j - 1 ];
if a == b {
f [ i ][ j ] = f [ i - 1 ][ j - 1 ];
} else {
f [ i ][ j ] = std :: cmp :: min ( f [ i - 1 ][ j ], f [ i ][ j - 1 ]) + 1 ;
}
}
}
f [ m ][ n ]
}
}
GitHub