2.3
1..买卖股票的最佳时机
2..买卖股票的最佳时机II
3.最长递增子序列
4.最长连续递增的子序列
5.最长重复子数组
6.最长公共子序列
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/
定义:dp[i][0] 表示第i天持有股票所得现⾦。dp[i][1] 表示第i天不持有股票所得现⾦。
所以dp[i][0]的转移有两种方向,
第一点是没有卖股票所以保持上一次的状态为dp[i-1][0]
第二点是买了股票,所以为买掉股票的钱
所以得到了转移方程:dp[i][0] = max(dp[i - 1][0], -prices[i]);
dp[i][1]也同样有两种方向
第一点,没有买进股票保持上一次的状态dp[i-1][1]
第二点,卖了股票,所以就是当前卖股票的钱
所以转移方程为:dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
class Solution {
public:
int maxProfit(vector& prices) {
int len=prices.size();
vector >dp(len,vector(2));
dp[0][0]-=prices[0],dp[0][1]=0;
for (int i=1;i
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/
同样有两个状态
dp[i][0] 表示第i天持有股票所得现⾦
dp[i][1] 表示第i天不持有股票所得最多现⾦
但唯一不同的是,卖掉股票之后,还可以继续买进
所以dp[i][0]的转移有两种方向,
第一点是没有卖股票所以保持上一次的状态为dp[i-1][0]
第二点是第i天卖了股票股票,第i-1天所有的钱减去买掉股票的钱
所以得到了转移方程:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
dp[i][1]也同样有两种方向
第一点,没有买进股票保持上一次的状态dp[i-1][1]
第二点,卖了股票,所以就是当前卖股票的钱
所以转移方程为:dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
class Solution {
public:
int maxProfit(vector& prices) {
int len = prices.size();
vector >dp(len,vector(2,0));
dp[0][0]-=prices[0],dp[0][1]=0;
//0表示持有股票,1表示不持有股票,持有股票的状态是由不持有股票买股票转移
//不持有股票的状态是由持有股票后卖掉股票得到
for (int i=1;i
https://leetcode.cn/problems/longest-increasing-subsequence/description/
由于是找到最长的递增的子序列,因此没有严格要求是递增的,那么建立dp[i]表示i之前最长的递增子序列,通过双循环i,j,j可以从头遍历到i-1,如果符合nums[i]>nums[j],那么dp就可以+1,因此得到转移方程:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
由于是找子序列,所以最短的子序列的长度一定是1,所以所有的初始化应该是1.
class Solution {
public:
int lengthOfLIS(vector& nums) {
vectordp(nums.size()+1,1);
int res=1;
for (int i=0;inums[j]){
dp[i]=max(dp[i],dp[j]+1);
if (res
https://leetcode.cn/problems/longest-continuous-increasing-subsequence/description/
这题和上一题的区别就在是否连续,这道题需要连续的递增子序列,所以dp数组只需要和前面一个数比较,如果大于前面一个数,那么当前状态就需要+1,否则就继续进行遍历。
class Solution {
public:
int findLengthOfLCIS(vector& nums) {
vectordp(nums.size()+1,1);
int maxn=1;
for (int i=1;inums[i-1]){
dp[i]=dp[i-1]+1;
if (dp[i]>maxn) maxn=dp[i];
}
}
return maxn;
}
};
https://leetcode.cn/problems/maximum-length-of-repeated-subarray/description/
定义dp[i][j]数组为下标i-1,和j-1的子串的最长重复子串的长度
转移方程:dp[i][j]只能当i-1和j-1上的字符相等的时候才能转换过来
class Solution {
public:
int findLength(vector& nums1, vector& nums2) {
int dp[1005][1005];
memset(dp,0,sizeof(dp));
int maxn=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;
if (maxn
https://leetcode.cn/problems/longest-common-subsequence/description/
这题和上一题的区别就在于这个不需要连续,所以dp[i][j]这个状态就不只是可以从dp[i-1][j-1]这个状态推出了,可以继承前面的最大子序列,如果相等就在前者就基础上加一,反之就继承前面的最大子序列
所以转移方程分为两种情况,第一种相等:
dp[i][j] = dp[i - 1][j - 1] + 1;
如果不相等:
那就看看text1[0, i - 2]与text2[0, j - 1]的最⻓公共⼦序列 和 text1[0, i - 1]与text2[0, j - 2]的最⻓公共⼦序列,取最⼤的。
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int dp[1005][1005];
memset(dp,0,sizeof(dp));
int maxn=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]);
}
}
}
return dp[text1.size()][text2.size()];
}
};