2.3学习总结

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()];
    }
};

你可能感兴趣的:(学习)