思路
定义dp[i][j]为word1的前i个字符和word2的前j个字符相同需要的最少操作
也就是说在递归的时候是从后面往前面递归的。
为什么会这么想
首先,转移方程是好写的。但是实现的过程是需要细节的。首先是basecase。经过了股票问题的思考后。在这里,当i<0或者j<0的情况,很容易返回另一个的对应情况。这个没什么好说的。关键是构建一个能够查找结果的表。
我的创新
这里使用的是做了一个map<string,int>,在每一个递归的过程中,根据i,j生成 i#j 这种格式的label,然后查找的时候,我们不再是按照以前的去找dp[i][j],我们只需要去找 string i#j 是否在hashtable中即可。这样的方式是非常简单而且容易理解的。
代码
class Solution {
public:
int dp(string& word1,string& word2,int i,int j,unordered_map<string,int>& mp){
if(i<0&&j<0)return 0;
if(i<0)return j+1;
if(j<0)return i+1;
//构建label
string label=to_string(i)+"#"+to_string(j);
//查找label是否在mp中
if(mp.count(label)!=0)return mp[label];
//最多操作n1+n2次,这里不需要设置为INT_MAX
int res=word1.size()+word2.size();
if(word1[i]==word2[j]){
res=dp(word1,word2,i-1,j-1,mp);
}
else{
res=min({dp(word1,word2,i-1,j-1,mp),dp(word1,word2,i-1,j,mp),dp(word1,word2,i,j-1,mp)})+1;
}
//在hashtable中建立label
mp[label]=res;
return res;
}
//定义dp[i][j]为word1的前i个字符和word2的前j个字符相同需要的最少操作数,i的范围为[0,word1.size-1]
int minDistance(string word1, string word2) {
int n1=word1.size();
int n2=word2.size();
unordered_map<string,int> mp;
return dp(word1,word2,n1-1,n2-1,mp);
}
};