动态规划DP(七) 股票交易

1.股票交易

在股票买卖的最佳时机问题中,给定一个数组,数组中的每个元素代表某一天的股票价格。你可以进行多次买入和卖出,但是必须在再次购买前卖出之前的股票。目标是找到最大的利润。

动态规划可以用于解决股票交易类的问题,其中最常见的问题是股票买卖的最佳时机问题(Best Time to Buy and Sell Stock)。

2.题目

1)

力扣icon-default.png?t=N658https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/找到当前位置之前的元素中的最小值,与当前位置的元素相减,遍历一维数组,找到最大差值。

class Solution {
public:
    int maxProfit(vector& prices) {
        int minp = prices[0];
        int n = prices.size();
        int res = 0;
        for(int i=1;i

2)

力扣icon-default.png?t=N658https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/这道题的难点在于最多购买股票两次,如果一直顺序考虑股票数组,就会变得很复杂,需要记录的值很多。

所有可以顺序加逆序考虑:

顺序:找到当前位置之前的最小值,当前位置元素与之计算差值,保留最大的差值。

逆序:找到当前位置之后的最大值,最大值与当前位置元素计算差值,保留最大的差值。

这样对于每个位置,都知道了这个位置之前一次购买卖出的最大利润,和这个位置以及这个位置之后一次购买卖出的最大利润。

把这个两个值相加,得到的就是每个位置最多购买两次彩票时的最大值。

class Solution {
public:
    int maxProfit(vector& prices) {
        int n = prices.size();

        vector dp(n,0);
        int minp = prices[0];
        for(int i=1;i dp2(n,0);
        int maxp = prices[n-1];
        for(int i=n-2;i>=0;i--){
            dp2[i] = max(dp2[i+1], maxp-prices[i]);
            maxp = max(maxp, prices[i]);
        }

        int res = 0;
        for(int i=0;i

3)

力扣icon-default.png?t=N658https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/题解:

这题需要额外考虑完成k次交易这一因素

所以转移方程为:buy[i][j]代表遍历prices[0...i]完成j笔交易,且此刻持有一只股票的最大收益。

sell[i][j]代表遍历prices[0...i]完成j笔交易,且此刻不持有股票的最大收益。

所以buy[i][j] = max(buy[i-1][j], sell[i-1][j]-prices[i])

取只考虑i-1只股票且完成j笔交易手上有股票的收益,或者只考虑i-1只股票且完成j笔交易购买当前这只股票收益

sell[i][j] = max(sell[i-1][j], buy[i-1][j-1]+prices[i])

取只考虑i-1只股票且完成j笔交易手上没有股票的收益,或者只考虑i-1只股票且此时卖出股票收益达到j笔交易的收益

这题好绕啊,建议自己码一下,会清晰很多。

代码:

class Solution {
public:
    int maxProfit(int k, vector& prices) {
        int n = prices.size();
        vector> buy(n,vector(k+1,INT_MIN/2));
        vector> sell(n,vector(k+1,INT_MIN/2));
        if(2*k>=n) k = n/2;

        buy[0][0] = -prices[0];
        sell[0][0] = 0;
        
        for(int i=1;i=0?res:0;
    }
};

因为是二维数组,且每次更新只用到[i-1]的值,所以肯定是可以压缩的。

压缩后,因为buy在sell前更新,所以 sell[i][j] = max(sell[i-1][j], buy[i-1][j-1]+prices[i])

就变成了 sell[i][j] = max(sell[i-1][j], buy[i][j-1]+prices[i])

又因为buy[i][j-1] = max(buy[i-1][j-1], sell[i-1][j-1]-prices[i]);

代入 sell[i][j],得到 sell[i][j] = max(sell[i-1][j], buy[i-1][j-1]+prices[i],sell[i-1][j-1] -prices[i]+prices[i])

比原本的 sell[i][j]多出了这一项:sell[i-1][j-1] -prices[i]+prices[i]

这一项表示在前i-1只股票中完成了j-1次交易,然后第j次交易是卖入第i只股票再在当天卖出。

所以也是sell[i-1][j]的一种特殊情况,所以多出的这一项不会比sell[i-1][j]大,也就不会影响最终的结果了。

所以是可以压缩数组的。

class Solution {
public:
    int maxProfit(int k, vector& prices) {
        int n = prices.size();
        vector buy(k+1,INT_MIN/2);
        vector sell(k+1,INT_MIN/2);
        if(2*k>=n) k = n/2;

        buy[0] = -prices[0];
        sell[0] = 0;
        
        for(int i=1;i=0?res:0;
    }
};

速度明显变快了:

动态规划DP(七) 股票交易_第1张图片

 4)

力扣icon-default.png?t=N658https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/

股票交易的题,最后代码都不复杂,但是设计转移方程的过程真的很绕。

这题多了一个冷冻期,也就是除了买和卖之外,又多了一个冷冻的状态。

dp[i]表示第i天结束之后的最大收益:

  • dp[i][0]表示第i天结束之后,手上持有一只股票
  • dp[i][1]表示第i天结束之后,手上不持有股票,且处于冷冻期
  • dp[i][1]表示第i天结束之后,手上不持有股票,不处于冷冻期

接下来分类讨论:

dp[i][0]表示第i天结束之后,手上持有一只股票

所以手上这只股票可以是今天买的,也可以是前一天就买了的

dp[i]][0] = max(dp[i-1][2]-prices[i], dp[i-1][0])

dp[i][1]表示第i天结束之后,手上不持有股票,且处于冷冻期

这表示第i天卖了股票,所以第i天结束之后,才会处于冷冻期

dp[i]][0] = dp[i-1][0]+prices[i]

dp[i][1]表示第i天结束之后,手上不持有股票,不处于冷冻期

第i天结束之后不处于冷冻期,那么前一天结束之后可以是冷冻期,也可以不是冷冻期

dp[i]][0] = max(dp[i-1][2], dp[i-1][1])

代码:

class Solution {
public:
    int maxProfit(vector& prices) {
        int n = prices.size();
        vector> dp(n, vector(3,INT_MIN/2));
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        dp[0][2] = 0;

        for(int i=1;i

转移方程中dp[i]只与dp[i-1]相关,所以可以压缩转移方程。简单地用六个变量来代替二维数组。

class Solution {
public:
    int maxProfit(vector& prices) {
        int n = prices.size();
        vector> dp(n, vector(3,INT_MIN/2));
        int f0,f1,f2,f3,f4,f5;
        f0 = -prices[0];
        f1 = 0;
        f2 = 0;

        for(int i=1;i

速度快了很多:

动态规划DP(七) 股票交易_第2张图片

 

你可能感兴趣的:(leetcode(c++),动态规划,算法,c++,面试)