题目来源:https://leetcode-cn.com/problems/delete-operation-for-two-strings/
题目描述
给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
示例:
输入: “sea”, “eat”
输出: 2
解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
提示:
给定单词的长度不超过500。
给定单词中的字符只含有小写字母。
题目大意
- 经典动态规划题
- 动态规划的五步骤:
- 确定dp数组和下标含义:dp[i][j]代表以i-1结尾的字符串word1和以j-1为结尾的字符串word2
- 确定递推公式:
d p [ i ] [ j ] = { d p [ i − 1 ] [ j − 1 ] ( i f w o r d 1 [ i − 1 ] = = w o r d 2 [ j − 1 ] ) e l s e m i n ( m i n ( d p [ i ] [ j − 1 ] + 1 , d p [ i − 1 ] [ j ] + 1 ) , d p [ i − 1 ] [ j − 1 ] + 2 ) dp[i][j]= \left \{ \begin{array} {c}dp[i-1][j-1]{\quad}(if{\quad}word1[i-1]==word2[j-1]) \\else \\min(min(dp[i][j-1]+1,dp[i-1][j]+1),dp[i-1][j-1]+2){\quad} \end{array} \right. dp[i][j]=⎩⎨⎧dp[i−1][j−1](ifword1[i−1]==word2[j−1])elsemin(min(dp[i][j−1]+1,dp[i−1][j]+1),dp[i−1][j−1]+2)
- 继续
- 如何定义和初始化dp数组
- 确定遍历顺序
- 举例推导dp数组
动态规划
- 在初始化的时候,我们需要对dp[i][0]和dp[0][j]进行遍历,因为此时是数组dp的最初状态,即对word1或word2是空串是进行初始化
- 在确定完这五步后,思路就清晰了
class Solution {
public:
int minDistance(string word1, string word2) {
int len1 = word1.size(), len2 = word2.size();
vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1));
for (int i = 0 ; i <= len1 ; ++i) dp[i][0] = i;
for (int j = 0 ; j <= len2 ; ++j) dp[0][j] = j;
for (int i = 1 ; i <= len1 ; ++i){
for (int j = 1 ; j <= len2 ; ++j){
if (word1[i - 1] == word2[j - 1]){
dp[i][j] = dp[i - 1][j - 1];
}
else{
dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 2);
}
}
}
return dp[len1][len2];
}
};
复杂度分析
- 时间复杂度:O(m*n)。n为数组的长度
- 空间复杂度:O(m*n)。n为数组的长度,维护了一个二维dp数组,二维长度为word1的长度,二维中的一维数组为word2的长度