1143 最长公共子序列
题目链接:1143
思路:定义dp[i][j]
为text1:[0,i-1]
和text2:[0,j-1]
的最长公共子序列的长度。当text1[i-1]==text2[j-1]
时,最长公共子序列一定为text1:[0,i-2]
和text2:[0,j-2]
中的最长公共子序列分别加上text1[i-1]
和text2[j-1]
,长度为dp[i-1][j-1]+1
;当text1[i-1]!=text2[j-1]
时,最长公共子序列可能从text1:[0,i-2]
和text2:[0,j-1]
中取,也可能从text1:[0,i-1]
和text2:[0,j-2]
中取,二者取大的,即长度为max(dp[i-1][j],dp[i][j-1])
。dp[i][0]
和dp[0][j]
虽然没有意义,但初始化为0,可用于推出dp[1][j]
和dp[i][1]
。
代码:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
vector<vector<int>> dp(text1.size()+1, vector<int>(text2.size()+1, 0));
int result = 0;
for (int i=1; i<=text1.size(); ++i) {
for (int j=1; j<=text2.size(); ++j) {
if (text1[i-1] == text2[j-1]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
if (dp[i][j] > result) result = dp[i][j];
}
}
return result;
}
};
1035 不相交的线
题目链接:1035
思路:可以发现,只要按顺序连就不会相交,即题目可以转换为求两个数组中的最长公共子序列,与1143 最长公共子序列相同。
代码:
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
vector<vector<int>> dp(nums1.size()+1, vector<int>(nums2.size()+1, 0));
int result = 0;
for (int i=1; i<=nums1.size(); ++i) {
for (int j=1; j<=nums2.size(); ++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]);
if (dp[i][j] > result) result = dp[i][j];
}
}
return result;
}
};
53 最大子数组和
题目链接:53
思路:定义dp[i]
为以nums[i]
结尾的最大和。要得到以nums[i]
结尾的子数组,若要和前面的数字连成一个子数组,则和最大的一定是和以nums[i-1]
结尾的最大和子数组拼接。若dp[i-1]>0
,则此时拼接的子数组和大于单个nums[i]
,最大和为dp[i-1]+nums[i]
; 若dp[i-1]<=0
,则拼接的子数组和小于单个nums[i]
,最大和为nums[i]
。
代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size());
dp[0] = nums[0];
int result = dp[0];
for (int i=1; i<nums.size(); ++i) {
if (dp[i-1] > 0) dp[i] = dp[i-1] + nums[i];
else dp[i] = nums[i];
if (dp[i] > result) result = dp[i];
}
return result;
}
};