//给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
//
//
//
// 示例:
//
// 输入: "sea", "eat"
//输出: 2
//解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
//
//
//
//
// 提示:
//
//
// 给定单词的长度不超过500。
// 给定单词中的字符只含有小写字母。
//
// Related Topics 字符串
// 👍 158 👎 0
题目的隐藏含义是:寻找两个字符串的最长公共子序列。
即,字符在字符串中的相对顺序一定,但不必连续。
删除最少的字符使两个单词相等,得到的删除后的结果就是最长子序列。
动态规划
以两个字符串的长度,定义一个数组。dp[i][j]代表word1的前i位和word2的前j位中包含的最长公共子序列长度。
如果word1[i] == word2[j],说明在两个字符串的i,j位置出现了相同的字符,这种情况直接可以选取前面的数值+1。
如果word1[i] != word2[j],说明i,j位置的字符不想等,此时的最长子序列长度是i,j位置前的长度,因为没有找到相同字符,所以长度跟前面长度的最长长度相等。
class Solution {
public int minDistance(String word1, String word2) {
// 0位置代表两个空字符串的比较
int[][] dp = new int[word1.length() + 1][word2.length() + 1];
// 从1开始,因为空字符串和任何字符串的公共子序列长度都是0
for (int i = 1; i <= word1.length(); i++) {
for (int j = 1; j <= word2.length(); j++) {
// i指向1的时候,实际上选择的字符是第0个,因此需要-1
if (word1.charAt(i - 1) == word2.charAt(j - 1)){
// 如果选择的两个字符相等,直接取这两个位置前面的值再加1即可
dp[i][j] = dp[i-1][j-1] + 1;
}else {
// 如果选择的两个字符不想等,要么不选i位置的字符,要么不选j位置的字符
// 选之前最长的公共子序列长度
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
// dp[word1.length()][word2.length()]就是最长公共子序列的长度,要删除的字符就是总字符减去这个值*2
return word1.length() + word2.length() - 2 * dp[word1.length()][word2.length()];
}
}