这道题是公共子序列,因此当字符不相等时,有dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);,而不是归零,因为子序列不要求连续
AC代码:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int n = text1.size();
int m = text2.size();
// dp[i][j]:长度为i的text1与长度为j的text2的最长公共子序列的长度
vector<vector<int>> dp(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[n][m];
}
};
和1143. 最长公共子序列一样,求最大连线数就是最长的公共子序列,因为相同的子序列有着相同的顺序,其中的各个元素相连也是互不交叉的。
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
int m = nums2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[n][m];
}
};
明确dp数组定义:以nums[i]结尾的子数组的最大和
因此dp[i]有两个方向可以推出:
dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和nums[i],即:从头开始计算当前连续子序列和 我们还需要一个变量来记录最大和,因为有着最大和的子数组不一定以最后一个数结尾
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n);
dp[0] = nums[0];
int res = dp[0];
for (int i = 1; i < n; ++i) {
dp[i] = max(nums[i] + dp[i - 1], nums[i]);
res = max(res, dp[i]);
}
return res;
}
};
- 392. 判断子序列 和1143. 最长公共子序列逻辑类似,只不过最后改为判断得到的长度是否等于t的长度
class Solution {
public:
bool isSubsequence(string s, string t) {
int n = s.size();
int m = t.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (s[i - 1] == t[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[n][m] == n;
}
};