1143.最长公共子序列、1035.不相交的线、53.最大子数组和
1143.最长公共子序列
对于最长公共子序列,我们可以用二维动态数组进行解决。
我们定义一个二维数组dp行数为text1.size()+1列数为text2.size()+1,dp[ii][jj]表示text1中0-ii-1个元素和text2中0-jj-1个元素中最长的公共子序列。
对于两个数组中的每一个元素都有两种可能,
两个元素相等于或者不相等,如果两个元素相等,那么我们他的最长公共子序列应该等于左上元素(两个数组分别前一个元素对应的最长公共最序列)+1,这样表示可以得到更长的公共序列。
于此同时,如果两个元素不相等,那么这个元素应该更新为二维数组左边和上边的较大者,继承可能存在的最大子序列长度。
动态规划四部曲。
1.dp数组的含义。dp[ii][jj]表示text1中0-ii-1和text2中0-jj-1中最长公共子序列。
2.dp数组的递推公式。
if(text1[ii-1] == text2[jj-1])
dp[ii][jj] = dp[ii-1][jj-1]+1;
else
dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);
3.dp数组的初始化。我们令所有第一行和第一列的元素全为0,表示,下标0到下标-1的元素最长公共子序列长度为0,便于进行元素的递推。
4.遍历顺序,先遍历text1或者先遍历text2都可以。
代码
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));
for(int ii =1;ii<text1.size()+1;ii++)
{
for(int jj =1;jj<text2.size()+1;jj++)
{
if(text1[ii-1] == text2[jj-1])
dp[ii][jj] = dp[ii-1][jj-1]+1;
else
dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);
}
}
return dp[text1.size()][text2.size()];
}
};
1035.不相交的线
这道题与上面的题类似,不对,本质一模一样,甚至将数组名改一下提交就能通过。不再过多解释。
代码
class Solution {
public:
int maxUncrossedLines(vector<int>& text1, vector<int>& text2) {
vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));
for(int ii =1;ii<text1.size()+1;ii++)
{
for(int jj =1;jj<text2.size()+1;jj++)
{
if(text1[ii-1] == text2[jj-1])
dp[ii][jj] = dp[ii-1][jj-1]+1;
else
dp[ii][jj] = max(dp[ii-1][jj],dp[ii][jj-1]);
}
}
return dp[text1.size()][text2.size()];
}
};
53.最大子数组和
对于该题,我们之前利用贪心算法做过一次,此处不再提,将用动态规划的思路进行解决。
我们要求最大的连续子数组和,因此我们可以用dp数组记录以ii-1为结尾的最大子数组和,将首项初始化为最小整数,方便推导后续元素。例如 1 2 -1 -5 3,他们的dp数组即为INT_MIN 1 2 1 -5 3.
因此我们更新dp数组的思路为:如果dp[ii-1]小于零,我们就让dp[ii]=nums[ii-1],不然的话,将让dp[ii]=dp[ii-1]+nums[ii-1]。
动态规划四部曲。
1.dp数组的含义。dp[ii][jj]表示以nums[ii-1]结尾的元素所能表示的最大子数组和。
2.dp数组的递推公式。如上所说,我们的代码为
dp[ii] = max(dp[ii-1],0)+nums[ii-1];
3.dp数组的初始化。我们让dp数组的首元素即为最小的整数即vector<int>dp(nums.size()+1,INT_MIN);
4.遍历顺序。我们从前向后进行遍历。
代码
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int>dp(nums.size()+1,INT_MIN);
if(nums.size()==1) return nums[0];
int result = nums[0];
for(int ii =1;ii<nums.size()+1;ii++)
{
dp[ii] = max(dp[ii-1],0)+nums[ii-1];
result = max(dp[ii],result);
}
return result;
}
};