leetcode_for_rust/cd0072_edit_distance/
mod.rs

1//! Edit Distance [leetcode: edit_distance](https://leetcode.com/problems/edit-distance/)
2//!
3//! Given two words *word1* and *word2*, find the minimum number of operations required to convert *word1* to *word2*.
4//!
5//! You have the following 3 operations permitted on a word:
6//! 1. Insert a character
7//! 2. Delete a character
8//! 3. Replace a character
9//!
10//! **Example1:**
11//!
12//! ```
13//! Input: word1 = "horse", word2 = "ros"
14//! Output: 3
15//! Explanation:
16//! horse -> rorse (replace 'h' with 'r')
17//! rorse -> rose (remove 'r')
18//! rose -> ros (remove 'e')
19//! ```
20//!
21//! **Example2:**
22//!
23//! ```
24//! Input: word1 = "intention", word2 = "execution"
25//! Output: 5
26//! Explanation:
27//! intention -> inention (remove 't')
28//! inention -> enention (replace 'i' with 'e')
29//! enention -> exention (replace 'n' with 'x')
30//! exention -> exection (replace 'n' with 'c')
31//! exection -> execution (insert 'u')
32//! ```
33//!
34
35/// # Solutions
36///
37/// # Approach 1: Dynamic Programming
38///
39/// * Time complexity: O(m*n)
40///
41/// * Space complexity: O(m*n)
42///
43/// * Runtime: 4 ms
44/// * Memory: 4.5 MB
45///
46/// ```rust
47/// impl Solution {
48///     pub fn min_distance(word1: String, word2: String) -> i32 {
49///         let word1_bytes = word1.into_bytes();
50///         let word2_bytes = word2.into_bytes();
51///         let m = word1_bytes.len();
52///         let n = word2_bytes.len();
53///         let mut dp = vec![vec![0; n + 1]; m + 1];
54///
55///         // number of deletions to reach word2[0]
56///         for i in 0..=m { dp[i][0] = i; }
57///         // to construct word2[j] just with word1[0] need to j insertions
58///         for j in 0..=n { dp[0][j] = j; }
59///
60///         for i in 1..=m {
61///             for j in 1..=n {
62///                 // we can obtain word2[0..j] from word1[0..i] either by
63///                 // deleting the ith charactor. knowing eg: dp[i - 1][j]
64///                 // inserting the jth charactor. knowing eg: dp[i][j - 1]
65///                 // or replate ith charactor with jth charactor. knowing eg: dp[i - 1][j - 1]
66///                 dp[i][j] = (dp[i - 1][j - 1] + (word1_bytes[i - 1] != word2_bytes[j - 1]) as usize)
67///                 .min(dp[i - 1][j] + 1)
68///                 .min(dp[i][j - 1] + 1);
69///             }
70///         }
71///         dp[m][n] as i32
72///     }
73/// }
74/// ```
75///
76/// # Approach 2: Dynamic Programming
77///
78/// * Time complexity: O(m*n)
79///
80/// * Space complexity: O(m*n)
81///
82/// * Runtime: 4 ms
83/// * Memory: 4.5 MB
84///
85/// ```rust
86/// impl Solution {
87///     pub fn min_distance(word1: String, word2: String) -> i32 {
88///         let word1_bytes = word1.into_bytes();
89///         let word2_bytes = word2.into_bytes();
90///         let m = word1_bytes.len();
91///         let n = word2_bytes.len();
92///         let mut dp = vec![vec![0; n + 1]; m + 1];
93///
94///         // number of deletions to reach word2[0]
95///         for i in 0..=m { dp[i][0] = i; }
96///         // to construct word2[j] just with word1[0] need to j insertions
97///         for j in 0..=n { dp[0][j] = j; }
98///
99///         for i in 1..=m {
100///             for j in 1..=n {
101///                 if word1_bytes[i - 1] == word2_bytes[j - 1] {
102///                     dp[i][j] = dp[i - 1][j - 1];
103///                 } else {
104///                     // we can obtain word2[0..j] from word1[0..i] either by
105///                     // deleting the ith charactor. knowing eg: dp[i - 1][j]
106///                     // inserting the jth charactor. knowing eg: dp[i][j - 1]
107///                     // or replate ith charactor with jth charactor. knowing eg: dp[i - 1][j - 1]
108///                     dp[i][j] = dp[i - 1][j].min(dp[i][j - 1]).min(dp[i - 1][j - 1]) + 1;
109///                 }
110///             }
111///         }
112///         dp[m][n] as i32
113///     }
114/// }
115/// ```
116///
117
118pub fn min_distance(word1: String, word2: String) -> i32 {
119    let word1_bytes = word1.into_bytes();
120    let word2_bytes = word2.into_bytes();
121    let m = word1_bytes.len();
122    let n = word2_bytes.len();
123    let mut dp = vec![vec![0; n + 1]; m + 1];
124
125    // number of deletions to reach word2[0]
126    for i in 0..=m { dp[i][0] = i; }
127    // to construct word2[j] just with word1[0] need to j insertions
128    for j in 0..=n { dp[0][j] = j; }
129
130    for i in 1..=m {
131        for j in 1..=n {
132            // we can obtain word2[0..j] from word1[0..i] either by
133            // deleting the ith charactor. knowing eg: dp[i - 1][j]
134            // inserting the jth charactor. knowing eg: dp[i][j - 1]
135            // or replate ith charactor with jth charactor. knowing eg: dp[i - 1][j - 1]
136            dp[i][j] = (dp[i - 1][j - 1] + (word1_bytes[i - 1] != word2_bytes[j - 1]) as usize)
137            .min(dp[i - 1][j] + 1)
138            .min(dp[i][j - 1] + 1);
139        }
140    }
141    dp[m][n] as i32
142}