115.不同的子序列
解题思路
这题一开始想用滚动数组的办法做,后来发现并不行,因为要去的是连续,并且可以跳元素,但是总体顺序不能变,因此需要从前往后遍历,这就不满足滚动数组需要的倒序遍历了。和连续情况不一样的是,即使当前的元素不相等,也要找到前面符合要求的最长子序列,保证后续结果正确。
解法
class Solution {
public:
int numDistinct(string s, string t) {
int n1 = s.size();
int n2 = t.size();
if(n2 > n1) return 0;
vector<vector<uint64_t>> dp(n2+1, vector<uint64_t>(n1+1, 0));
for(int j=0; j < n1; j++) dp[0][j] = 1;
for(int i=1; i<=n2; i++){
for(int j=1; j<=n1; j++){
if(t[i-1]==s[j-1])
dp[i][j] = dp[i-1][j-1] + dp[i][j-1]; // 加上前面满足条件的个数
else
dp[i][j] = dp[i][j-1];
}
}
return dp[n2][n1];
}
};
- 时间复杂度: O ( m n ) O(mn) O(mn)
- 空间复杂度: O ( m n ) O(mn) O(mn)
583. 两个字符串的删除操作
解题思路
和上一题很类似,变成了两个字符串都可删除。在递推的时候就是针对两个字符串对应下标的元素为尾元素进行,当尾元素相同时,dp[i][j]=dp[i-1][j-1],不相同时,dp[i][j]=min(dp[i-1][j]+1, dp[i][j-1] +1, dp[i-1][j-1]+2,以此保证对于每一个为尾元素得到的步数都是最小的呢,那么最终结果即为dp[n1][n2[。
解法
class Solution {
public:
int minDistance(string word1, string word2) {
int n1 = word1.size();
int n2 = word2.size();
vector<vector<int>> dp(n1+1, vector<int>(n2+1, 0));
for(int i=0; i<=n1; i++) dp[i][0] = i;
for(int j=1; j<=n2; j++) dp[0][j] = j;
for(int i=1; i<=n1; i++){
for(int j=1; j<=n2; 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, min(dp[i][j-1]+1, dp[i-1][j-1]+2));
}
}
}
return dp[n1][n2];
}
};
- 时间复杂度: O ( m n ) O(mn) O(mn)
- 空间复杂度: O ( m n ) O(mn) O(mn)
72. 编辑距离
解题思路
需要一点转化。这里一个字符串的添加操作可以等效为另一个字符串的删除操作,因此需要考虑的数量就减少了,替换操作相当于在两个字符串上一个下标匹配成功的基础上添加上相同的元素,因此最小的dp就在这三者之间,当尾元素相同时不需要操作。
解法
class Solution {
public:
int minDistance(string word1, string word2) {
int n1 = word1.size();
int n2 = word2.size();
vector<vector<int>> dp(n1+1, vector<int>(n2+1, 0));
for(int i=0; i<=n1; i++) dp[i][0] = i;
for(int j=1; j<=n2; j++) dp[0][j] = j;
for(int i=1; i<=n1; i++){
for(int j=1; j<=n2; 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, min(dp[i][j-1]+1, dp[i-1][j-1]+1));
}
}
}
return dp[n1][n2];
}
};
- 时间复杂度: O ( m n ) O(mn) O(mn)
- 空间复杂度: O ( m n ) O(mn) O(mn)
今日总结
国庆在忙答辩,补卡中()

1658

被折叠的 条评论
为什么被折叠?



