您的位置:首页 > 运维架构

leetcode 583. Delete Operation for Two Strings

2017-07-21 14:48 615 查看
Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same, where in each step you can delete one character in either string.

Example 1:

Input: "sea", "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".


Note:

The length of given words won't exceed 500.
Characters in given words can only be lower-case letters.

又是一个让我一筹莫展的题目。其实主要目的就是要找出两个字符串中的“共同最大子字符串的字符个数”,其实不能算是子字符串,因为相邻字符不一定要连接在一起,但是先后关系需要维持。看看solutions吧:https://leetcode.com/problems/delete-operation-for-two-strings/#/solution点进去有图解。
我模仿着DP方法写了一个解答。DP[i][j]中存储的是 word1[0 ~ i-1] 和 word2[0 ~ j-1] 两个字符串中的“共同最大子分布字符串的字符个数”(我瞎取的名字)。

package leetcode;

public class Delete_Operation_for_Two_Strings_583 {

public int minDistance(String word1, String word2) {
char[] wc1=word1.toCharArray();
char[] wc2=word2.toCharArray();
int[][] DP=new int[wc1.length+1][wc2.length+1];
for(int i=1;i<=wc1.length;i++){
for(int j=1;j<=wc2.length;j++){
char c1=wc1[i-1];
char c2=wc2[j-1];
if(c1==c2){
DP[i][j]=DP[i-1][j-1]+1;
}
else{
DP[i][j]=Math.max(DP[i-1][j], DP[i][j-1]);
}
}
}
int maxCommon=DP[wc1.length][wc2.length];
int result=(wc1.length-maxCommon)+(wc2.length-maxCommon);
return result;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Delete_Operation_for_Two_Strings_583 d=new Delete_Operation_for_Two_Strings_583();
System.out.println(d.minDistance("intention","execution"));
}

}


Solution


Approach #1 Using Longest Common Subsequence [Time Limit Exceeded]

Algorithm

In order to determine the minimum number of delete operations needed, we can make use of the length of the longest common sequence among the two given strings s1s1 and s2s2,
say given by lcslcs.
If we can find this lcslcs value,
we can easily determine the required result as m
+ n - 2*lcsm+n−2∗lcs.
Here, mm and nn refer
to the length of the two given strings s1s1 and s2s2.

The above equation works because in case of complete mismatch(i.e. if the two strings can't be equalized at all), the total number of delete operations required will be m
+ nm+n.
Now, if there is a common sequence among the two strings of length lcslcs,
we need to do lcslcs lesser
deletions in both the strings leading to a total of 2lcs2lcs lesser
deletions, which then leads to the above equation.

In order to find the length of the longest common sequence, we make use of a recursive function 
lcs(s1,s2,i,j)
 which
returns the length of the longest common sequence among the strings s1s1 and s2s2 considering
their lengths upto ii and jj respectively.
For evaluating the function, we check if the characters s1[m-1]s1[m−1] and s2[n-1]s2[n−1] for
equality. If they match, we can consider the corresponding strings upto 1 lesser lengths since the last characters have already been considered and add 1 to the result to be returned for strings of 1 lesser lengths. Thus, we make the function call 
lcs(s1,
s2, i-1, j-1)
.

If the last characters don't match, we have two options, either we can consider the second last character of s1s1 and
the last character of s2s2,
or we can consider the second last character of s2s2 and
the last character of s1s1.
We need to consider the larger result obtained out of the two considerations for getting the required length.

Thus, the function call 
lcs(s1,s2,m,n)
 returns the required lcslcs value.

Java

public class Solution {
public int minDistance(String s1, String s2) {
return s1.length() + s2.length() - 2 * lcs(s1, s2, s1.length(), s2.length());
}
public int lcs(String s1, String s2, int m, int n) {
if (m == 0 || n == 0)
return 0;
if (s1.charAt(m - 1) == s2.charAt(n - 1))
return 1 + lcs(s1, s2, m - 1, n - 1);
else
return Math.max(lcs(s1, s2, m, n - 1), lcs(s1, s2, m - 1, n));
}
}


Complexity Analysis

Time complexity : O(2^{max(m,n)})O(2​max(m,n)​​).
Size of recursion tree will be 2^(m+n)2​(​​m+n).
Here, mm and nn refer
to the lengths of s1s1 and s2s2 respectively.

Space complexity : O(\text{max}(m,n))O(max(m,n)).
The depth of the recursion tree will go upto \text{max}(m,n)max(m,n).


Approach #2 Longest Common Subsequence with Memoization [Accepted]

Algorithm

We can observe that in the last approach, while determining the lcslcs value,
a lot of redundant function calls are made, since the same mm and nn values
to be used for the function calls could be obtained going through many different paths. We can remove this redundancy by making use of a memomemo array
to store the value to be returned for these function calls if they have been called once with the corresponding parameters. Thus, memo[i][j]memo[i][j] is
used to store the result for the function call 
lcs(s1,s2,i,j)
.

Thus, by returning the already stored values from the memomemo array,
we can prune the search space to a great extent.

Java

public class Solution {
public int minDistance(String s1, String s2) {
int[][] memo = new int[s1.length() + 1][s2.length() + 1];
return s1.length() + s2.length() - 2 * lcs(s1, s2, s1.length(), s2.length(), memo);
}
public int lcs(String s1, String s2, int m, int n, int[][] memo) {
if (m == 0 || n == 0)
return 0;
if (memo[m][n] > 0)
return memo[m][n];
if (s1.charAt(m - 1) == s2.charAt(n - 1))
memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1, memo);
else
memo[m][n] = Math.max(lcs(s1, s2, m, n - 1, memo), lcs(s1, s2, m - 1, n, memo));
return memo[m][n];
}
}


Complexity Analysis

Time complexity : O(m*n)O(m∗n). memomemo array
of size mmxnn needs
to be filled once. Here, mm and nn refer
to the length of the strings s1s1 and s2s2 respectively.

Space complexity : O(m*n)O(m∗n). memomemo array
of size mmxnn is
used. Also, The depth of the recursion tree will go upto \text{max}(m,n)max(m,n).


Approach #3 Using Longest Common Subsequence- Dynamic Programming [Accepted]

Algorithm

Another method to obtain the value of lcslcs is
to make use of Dynamic Programming. We'll look at the implemenation and carry-on alongside the idea behind it.

We make use of a 2-D dpdp,
in which dp[i][j]dp[i][j] represents
the length of the longest common subsequence among the strings s1s1 and s2s2 considering
their lengths upto (i-1)^{th}(i−1)​th​​ index
and (j-1)^{th}(j−1)​th​​ index
only respectively. We fill the dpdp array
in row-by-row order.

In order to fill the entry for dp[i][j]dp[i][j],
we can have two cases:

The characters s1[i-1]s1[i−1] and s2[j-1]s2[j−1] match
with each other. In this case, the entry for dp[i][j]dp[i][j] will
be one more than the entry obtained for the strings considering their lengths upto one lesser index, since the matched character adds one to the length of LCS formed till the current indices. Thus, the dp[i][j]dp[i][j] entry
is updated as dp[i][j]
= 1 + dp[i-1][j-1]dp[i][j]=1+dp[i−1][j−1].
Note that dp[i-1][j-1]dp[i−1][j−1] has
been used because the matched character belongs to both s1s1 and s2s2.

The characters s1[i-1]s1[i−1] and s2[j-1]s2[j−1] don't
match with each other. In this case, we can't increment the current entry as compared to entries corresponding to the previous indices, but we need to replicate the previous entry again to indicate that the length of LCS upto the current indices also remains
the same. But, which entry to pick up? Now, since the current character hasn't matched, we have got two options. We can remove the current character from consideration from either s1s1 or s2s2 and
use the corresponding dpdp entries
given by dp[i-1][j]dp[i−1][j] and dp[i][j-1]dp[i][j−1] respectively.
Since we are considering the length of LCS upto the current indices we need to pick up the larger entry out of these two to update the current dpdp entry.

At the end, again, we obtain the number of deletions required as m
+ n - 2*dp[m]
m+n−2∗dp[m][n],
where mm and nn refer
to the lengths of s1s1 and s2s2. dp[m]
dp[m][n] now
refers to the length of LCS among the two given strings.

Java

public class Solution {
public int minDistance(String s1, String s2) {
int[][] dp = new int[s1.length() + 1][s2.length() + 1];
for (int i = 0; i <= s1.length(); i++) {
for (int j = 0; j <= s2.length(); j++) {
if (i == 0 || j == 0)
continue;
if (s1.charAt(i - 1) == s2.charAt(j - 1))
dp[i][j] = 1 + dp[i - 1][j - 1];
else
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
return s1.length() + s2.length() - 2 * dp[s1.length()][s2.length()];
}
}


Complexity Analysis

Time complexity : O(m*n)O(m∗n).
We need to fill in the dpdp array
of size mmxnn.
Here, mm and nn refer
to the lengths of s1s1 and s2s2.

Space complexity : O(m*n)O(m∗n). dpdp array
of size mmxnn is
used.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: