583.两个字符的删除操作
思路:返回两个字符相同的最少操作,两个字符都可以删减。定义dp数组,dp[i][j]表示返回以word1[i-1]结尾的单词和word2[j-1]结尾的单词 相同的最少操作数。递推公式,如果word1[i-1]==word2[j-1], dp[i][j] = dp[i-1][j-1]。否则,dp[i][j]可以由删除word1或者删除word2获得,min(dp[i-1][j]+1,dp[i][j-1]+1).初始化。dp[i][0]=i,dp[0][j]=j.遍历顺序:从小到大。打印dp数组,用于debug。
cpp
class Solution {
public:
int minDistance(string word1, string word2) {
//定义dp数组及其下标含义 dp[i][j]表示 以word1[i-1]结尾和以word2[j-1]结尾的单词,使他们相同的最小步数
//递推公式 如果word1[i-1]==word2[j-1], dp[i][j]=dp[i-1][j-1]. else dp[i][j] = min(dp[i-1][j],dp[i][j-1]).
//初始化 dp[i][0] = 1; dp[0][j] = 1;因为删一个就是空字符了
//遍历顺序,从小到大。
int size1 = word1.size();
int size2 = word2.size();
vector<vector<int>> dp(size1+1,vector<int>(size2+1,0));
for(int i =1;i<=size1;i++)
{
dp[i][0] = i;
}
for(int j =1;j<=size2;j++)
{
dp[0][j] = j;
}
for(int i =1;i<=size1;i++)
{
for(int j =1;j<=size2;j++)
{
if(word1[i-1]==word2[j-1])
{
dp[i][j] = dp[i-1][j-1];
}
else
{
dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1);
}
}
}
return dp[size1][size2];
}
};
72.编辑距离
思路:跟上道题一样,只不过在word1[i-1]和word2[j-1]不相同时,dp[i][j]可以被多种情况推出,可以由dp[i-1][j]+1,dp[i][j-1]+1,相当于删减了一个字母,或者由dp[i-1][j-1]+1推出,相当于变换了一个字母。
cpp
class Solution {
public:
int minDistance(string word1, string word2) {
//dp数组及其下标的含义 dp[i][j]表示以word1[i-1]结尾的单词变成以word2[j-1]结尾的单词的最少操作数
//递推公式 如果word1[i-1]==word2[j-1], dp[i][j] = dp[i-1][j-1];
//否则有多种情况,1、替换一个字符 dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2);
//初始化
int size1 = word1.size();
int size2 = word2.size();
vector<vector<int>> dp(size1+1,vector<int>(size2+1,0));
for(int i = 1;i<=size1;i++)
{
dp[i][0] = i;
}
for(int j =1;j<=size2;j++)
{
dp[0][j] = j;
}
for(int i =1;i<=size1;i++)
{
for(int j =1;j<=size2;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],dp[i][j-1])+1,dp[i-1][j-1]+1);
}
}
}
return dp[size1][size2];
}
};
收获:
编辑距离类问题,最好画出dp网格,确定初始化的含义及值,确定当i-1和j-1结尾的数组相等或不等时,dp[i][j]由几种情况推出。