package LeetCode_72
/**
* 72. Edit Distance
* https://leetcode.com/problems/edit-distance/description/
*
* Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.
You have the following 3 operations permitted on a word:
1.Insert a character
2.Delete a character
3.Replace a character
Example 1:
Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation:
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')
Example 2:
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')
* */
class Solution {
fun minDistance(word1: String, word2: String): Int {
//method 1:Time complexity is O(3^m), Space complexity is O(m*n),
//because has overlapping sub problems, for example editDistance(str1,str2,1,1) will call more time
val m = word1.length
val n = word2.length
//return editDistance(word1, word2, m, n)
//method 2: dp, Time complexity is O(m*n), Space complexity is O(m*n),
return editDistanceDP(word1, word2, m, n)
}
private fun editDistanceDP(str1: String, str2: String, m: Int, n: Int): Int {
val dp = Array(m + 1) { Array(n + 1, { 0 }) }
/*
There are following two different ways to store the values so that these values can be reused:
* a) Memoization (Top Down)
b) Tabulation (Bottom Up)
https://www.geeksforgeeks.org/overlapping-subproblems-property-in-dynamic-programming-dp-1/
* */
//fill dp array by bottom up manner
for (i in 0 .. m) {
for (j in 0 .. n) {
//if first string is empty,
if (i == 0) {
dp[i][j] = j
} else if (j == 0) {
//the second string is empty,
dp[i][j] = i
} else if (str1[i - 1] == str2[j - 1]) {
//if last character of two string are same, ignore last character
dp[i][j] = dp[i - 1][j - 1]
} else {
dp[i][j] = 1 + Math.min(
//insert and remove
Math.min(dp[i][j-1], dp[i-1][j])
//replace
, dp[i - 1][j - 1]
)
}
}
}
return dp[m][n]
}
private fun editDistance(str1: String, str2: String, m: Int, n: Int): Int {
//if first string is empty,
//the only option is insert into all chars of second string into the first
if (m == 0) {
return n
}
if (n == 0) {
return m
}
//if last character of two string are same, ignore last character
if (str1[m - 1] == str2[n - 1]) {
return editDistance(str1, str2, m - 1, n - 1)
}
//compute minimum cost for all three operations
return 1 + Math.min(
//insert and remove
Math.min(editDistance(str1, str2, m, n - 1), editDistance(str1, str2, m - 1, n)),
//replace
editDistance(str1, str2, m - 1, n - 1)
)
}
}