题意理解:
给定两个单词
word1
和word2
,返回使得word1
和word2
相同所需的最小步数。每步 可以删除任意一个字符串中的一个字符。
该题的要求是:当前有两个单词,要是两个单词剩余的部分相同,最少需要删除多少个字母。
这里有两个思路来求解这道题:
一种是设置合理的dp数组,通过动态规划的思路来求解最小的操作次数。
另一种方式是求解两个单词的最长公共子序列,然后两个单词长度和-二倍的最长公共子序列即为最小删除的次数。
解题思路:
动态规划:
(1)定义dp数组
dp[i][j]表示word1第i个元素前,word2第j个元素前要使两者相等需要删除的最小次数。
(2)递推公式
当word1[i-1]=word2[j-1]时
dp[i][j]=dp[i-1][j-1]
此时指示的两个单词相同,都删除和都不删,都能获得相同序列
但此时求最小删除数,所以不删除这两个字母
当word1[i-1]不等于word2[j-1]时
有三种情况:
删掉word1里的字母=dp[i-1][j]+1
删掉word2里的字母=dp[i][j-1]+1
删掉word1和word2里的字母=dp[i-1][j-1]+2
这里求最小操作数,所以有:
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2)
(3)初始化:
dp[0][j]表示word1是空串,word2有字符,删除j个字符即可,则有dp[0][j]=j
同理:dp[i][0]=i
1.动态规划解题
public int minDistance(String word1, String word2) {
int[][] dp=new int[word1.length()+1][word2.length()+1];
for(int i=0;i<=word1.length();i++){
dp[i][0]=i;
}
for(int j=1;j<=word2.length();j++){
dp[0][j]=j;
}
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
//不删
dp[i][j]=dp[i-1][j-1];
}else {
dp[i][j]=Math.min(Math.min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+2);
}
}
}
return dp[word1.length()][word2.length()];
}
2.求最长公共子序列解题
public int minDistance2(String word1, String word2) {
int[][] dp=new int[word1.length()+1][word2.length()+1];
for(int i=0;i<=word1.length();i++){
Arrays.fill(dp[i],0);
}
//求最长公共子序列
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
//不删
dp[i][j]=dp[i-1][j-1]+1;
}else {
dp[i][j]=Math.max(Math.max(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1]);
}
}
}
return word1.length()+word2.length()-2*dp[word1.length()][word2.length()];
}
3.复杂度分析
时间复杂度:O(n^2)
空间复杂度:O(n^2)