买卖股票的最佳时机II

继续每日一题,今天给大家分享一道经典的多维动态规划题目:买卖股票的最佳时机II

题目描述:

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

题目示例:
在这里插入图片描述

对于动态规划类的题目,无论是一维还是多维,我们的目的都是找到一个合适的状态转移方程来满足无后效性,对于本题,我们除了要标记收益之外还需要知道当前收益下的持股状态,所以我们声明dp数组:dp[i][j],表示:

下标为 i 的这一天,持股状态为 j 时,我们手上拥有的最大现金数。

j有两种状态:股票(1) or 现金(0)

  • dp[i][0]:表示在第i天持有现金的最大收益
  • dp[i][1]:表示第i天持有股票的最大收益

所以我们的公式如下;
d p [ i ] [ j ] = { M a t h . m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + p r i c e [ i ] ) ,   j = = 0   M a t h . m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] − p r i c e [ i ] ) ,   j = = 1   dp[i][j]= \begin{cases} Math.max(dp[i-1][0],dp[i-1][1]+price[i]), & \text{ $j==0$ } \\ Math.max(dp[i-1][1],dp[i-1][0]-price[i]), & \text{ $j==1$ } \end{cases} dp[i][j]={Math.max(dp[i1][0],dp[i1][1]+price[i]),Math.max(dp[i1][1],dp[i1][0]price[i]), j== j==
我来给大家解释一下每状态下的公式含义

  • dp[i][0]即当天持有的是现金的情况,这种情况需要我们在当天卖出股票换成钱

如果前一天持有的也是现金即dp[i-1][0],那么当天就无可卖出的股票,所以收益和前一天是一样的

如果前一天持有的是股票即dp[i-1][1],那么当天就有可卖出的股票,卖出的钱就是price[i],所以当天的收益为:p[i-1][1]+price[i]

  • dp[i][1]即当天持有的是股票的情况,这种情况需要我们买入股票

如果前一天持有的是股票即dp[i-1][1],因为题目要求无论在任何时候都只能有一支股票,所以当天就无法买入,收益和前一天一样

如果前一天持有的是现金即dp[i-1][0],那么当天就有可以买入股票,买入的价格则是price[i],此时我们的收益就需要减去买股票的钱,即:p[i-1][0]-price[i]

了解上面内容后,我们还有最后一点待定,就是初始值,在动态规划的题目中,我们的步骤就是确定动态转移方程以满足无后效性问题,第二步则是确定初始值

  • dp[0][0],第一天持有现金,则无任何收益,故:dp[0][0]=0;
  • dp[0][1],第一天持有股票,则需要买入,买入的价格为:price[0],故:dp[0][1]=0-price[0]

代码实现(java):

     public int maxProfit(int[] prices) {
        int n = prices.length;
        int[][] dp = new int[n][2];
        //0:持有现金 1:持有股票
        dp[0][0] = 0;
        dp[0][1] = 0 - prices[0];
        for (int i = 1; i < n; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        //找最大收益
        return Math.max(dp[n - 1][0], dp[n - 1][1]);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZNineSun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值