1143.最长公共子序列
思路:定义dp[i][j]为以nums[i-1]结尾的子序列1,和以nums2[j-1]结尾的子序列2,他们的最长公共子序列长度。递推公式,如果nums1[i-1] ==nums2[j-1] , dp[i][j] = dp[i-1][j-1]+1。如果不相等,dp[i][j]可以由dp[i][j-1]或者dp[i-1][j]推得,举例,子序列1为abcde,自序列2为acd,当i=2,j=2时,b不等于c,此时得dp[2][2]可以由ab与a的最长公共子序列个数或者,a和ac的最长公共子序列个数推的。
class Solution {
public:int longestCommonSubsequence(string text1, string text2) {//确定dp数组及其下标含义 dp[i][j]表示以 text1[i-1] text2[j-1]结尾的子序列//递推公式 如果 text1[i-1] ==text2[j-1]. dp[i][j] = dp[i-1][j-1]+1.int size1 = text1.size();int size2 = text2.size();vector<vector<int>> dp(size1+1,vector<int>(size2+1,0));int maxnum = 0;for(int i = 1;i<=size1;i++){for(int j=1;j<=size2;j++){if(text1[i-1]==text2[j-1]){dp[i][j] = dp[i-1][j-1]+1;maxnum = maxnum>dp[i][j]?maxnum:dp[i][j];}else{dp[i][j] = max(dp[i-1][j],dp[i][j-1]);}}}return maxnum;}
};
1035.不相交的线
思路:要想找到两个数组中的相同子数组,且相同数字连线不交叉,实际上与上道题相似,都是求最长公共子序列。子序列仍保持相对顺序。比如 ade和aed 最长公共子序列就是ad或者ae,这道题同理123,132满足条件的为12或者13,不会出现交叉的情况。
class Solution {
public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {//确定dp数组及其下标的含义 dp[i][j]代表以nums1[i-1]结尾的子序列,和以nums2[j-1]结尾的自序列中可绘制的最大连线数//递推公式 if(nums[i-1]==nums[j-1]) dp[i][j] j>iint size1 = nums1.size();int size2 = nums2.size();vector<vector<int>>dp(size1+1,vector<int>(size2+1,0));int maxnum = 0;for(int i = 1;i<=size1;i++){for(int j =1;j<=size2;j++){if(nums1[i-1]==nums2[j-1]){dp[i][j] = dp[i-1][j-1]+1;maxnum = maxnum>dp[i][j]?maxnum:dp[i][j];}else{dp[i][j] = max(dp[i-1][j],dp[i][j-1]);}}}return maxnum;}
};
53.最大子数组和
思路:确定dp数组及其下标含义dp[i]代表以nums[i]结尾的连续字数组的最大和。递推公式,dp[i]分两种情况,第一种由以nums[i-1]为结尾的连续子数组的最大和+nums[i]。第二种以nums[i]重新开头的子序列。
class Solution {
public:int maxSubArray(vector<int>& nums) {//dp[i]表示 到第i个元素为结尾时,连续子数组的最大和//if nums[i]>0 dp[i]= dp[]int size = nums.size();vector<int> dp(size,0);dp[0]=nums[0];int maxnum = dp[0];for(int i=1;i<size;i++){dp[i] = max(dp[i-1]+nums[i],nums[i]);maxnum = maxnum>dp[i]?maxnum:dp[i];}return maxnum;}
};