DP(三维DP数组) :买卖stock的best timing

DP(三维DP数组) + 暴力枚举:买卖stock的best timing

问题

在这里插入图片描述
在这里插入图片描述

思路

  题目中首先出现了两个影响利润的因素:天数(第几天)、最多允许的交易次数,我们的DP数组需要包含这两维,但仅仅有这两维我们还是无法进行状态转移,因为我们不知道某一天到底有没有买卖股票。我们需要发现判断某一天i是否买卖股票的关键在于判断第i天与之前第i - 1天的持股状态,若第i - 1天未持股,第i天持股,则第i天买了股票,否则没买;若第i - 1天持股,第i天不持股,则第i天卖出了股票,否则没卖出。因此我们继续增加DP数组到三维,第三维记录持股情况(是否持股)。
  我们设DP[j][i][0]表示最多允许交易i次,第j天不持股时的最高收益;DP[j][i][1]表示最多允许交易i次,第j天持股时的最高收益。状态转移方程如下:
  第j天不持股,要么就是第j-1天持股而在第j天卖了股票,要么就是第j-1天不持股而第j天也不买股票(a[]数组表示每天的股票价格):
  DP[j][i][0]=max(DP[j-1][i-1][1]+a[j],DP[j-1][i][0])
  第j天持股,要么是第j-1天不持股而在第j天买了股票,要么就是第j-1天持股,第j天不买股票:
  DP[j][i][1]=max(DP[j-1][i][0]-a[j],DP[j-1][i][1])
  通过上述状态转移方程,我们不需要考虑具体是买了哪一天的股票,而只需考虑当前是否持有某股票,总收益的计算也不需要用卖价-买价,而是若买股票,则总收益直接减去股票价格,若卖股票,总收益直接加上股票价格,这样更简单且与卖价-买价这种计算方式等价,最重要的是引入持股概念和总收益的简单计算方式,我们能抛开具体是买了哪天的股票这种细节,从而写出状态转移方程。
  我们利用一个双重循环即可求出DP数组,那么答案显然为DP[n][k][0],表示最多允许交易k次,第n天不持股时的最高收益。为什么不可能是DP[n][k][1]呢?因为如果最后一天持股了,在前面肯定有一天不持股的情况的最大收益比这个值大。因为若最后一天还有股票没卖出去,那又何必买这个股票,因此在买股票的那天,若不买股票,则收益一定比DP[n][k][1]大。
  再来看看双重循环的遍历顺序,我们一定是要先枚举最多允许的交易次数i,再遍历天数j(第几天)。利用减治的思想来解释,我们先枚举一个最大交易次数i,再遍历天数j,相当于解决了一个规模较小的问题,进而可以通过状态转移求解允许交易次数更大的问题。如果是先遍历天数,再遍历允许的交易次数,那么在逻辑上是没有道理的,实际上也达不到状态转移的效果。
  最后需要注意的点是:我们一定要对k值做预处理,设n为总天数,则k = Math.min(n / 2, k),因为n天中最多只能交易n / 2次。DP数组的初始值为j = 1即第一天的时候,若第一天持有股票,则dp[j][i][1] = (-1) * a[1],否则dp[j][i][0] = 0

代码

class Solution {
    
    
    static int[][][] dp = new int[1005][505][2];
    public int maxProfit(int k, int[] prices) {
    
    
        int n = prices.length;
        int i, j;
        k = Math.min(n / 2, k);
        for (i = 0; i <= k; i++) {
    
    
            for (j = 1; j <= n; j++) {
    
    
                if (j == 1) {
    
    
                    dp[j][i][1] = (-1) * prices[0];
                    dp[j][i][0] = 0;
                } else {
    
    
                    dp[j][i][0] = i > 0 ? Math.max(dp[j - 1][i - 1][1] + prices[j - 1], dp[j - 1][i][0]) : dp[j - 1][i][0];
                    dp[j][i][1] = Math.max(dp[j - 1][i][0] - prices[j - 1], dp[j - 1][i][1]);
                }
            }
        }
        return dp[n][k][0];
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44709990/article/details/121890015