day50买卖股票的最佳时机3&4

力扣123.买卖股票的最佳时机3

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/

思路

本题可以买卖两次,比买卖股票的最佳时机要多出几个状态。

dp数组的含义:

(1)dp[i][0]:第i天不操作的最大金额

(2)dp[i][1]:第i天第一次持有的最大金额

(3)dp[i][2]:第i天第一次不持有的最大金额

(4)dp[i][3]:第i天第二次持有的最大金额

(5)dp[i][4]:第i天第二次不持有的最大金额

递推公式:

(1)第i天不操作的情况只能由第i-1天不操作延续,实际上这个可以不写

(2)第i天第一次持有的最大金额可以由:1.前一天已经第一次持有;2.前一天未持有,在这天进行买入

(3)第i天第一次不持有的最大金额可以由:1.前一天已经第一次不持有;2.前一天持有,在这天进行卖出

(4)第i天第二次持有的最大金额可以由:1.前一天已经第二次持有;2.前一天未持有,在这天进行买入

(5)第i天第二次不持有的最大金额可以由:1.前一天已经第二次不持有;2.前一天持有,在这天进行卖出

初始化:

(1)dp[0][0]:不操作其实就是0

(2)dp[0][1]:第0天想要持有,只能进行买入

(3)dp[0][2]:第0天卖出,收益为0

(4)dp[0][3]:第0天第二次买入

(5)dp[0][4]:第0天第二次卖出,收益还是为0

遍历顺序

同买卖股票1

打印数组

最大金额肯定是第二次不持有,即dp[prices.length-1][4]

完整代码

class Solution {
    public int maxProfit(int[] prices) {
        int[][] dp = new int[prices.length][5];
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        dp[0][2] = 0;
        dp[0][3] = -prices[0];
        dp[0][4] = 0;
        for (int i = 1; i < prices.length; i++) {
            dp[i][0] = dp[i-1][0];
            dp[i][1] = Math.max(dp[i-1][1],-prices[i]);
            dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
            dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);
            dp[i][4] = Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);
        }
        return dp[prices.length-1][4];
    }
}

力扣188.买卖股票的最佳时机4

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/

思路

买卖2次需要4个状态来表示,那么买卖k次需要2k个状态来表示,加上dp[i][0]这个不操作的初始状态,需要2k+1个状态。

我们采用j来控制每次买卖的递推,j+1代表持有股票,j+2代表不持有股票,j每次跳跃2,就能表示所有的买卖状态。

初始化:观察可以得到,第0天时,当j为奇数时,是买入状态,金额是-prices[0];否则为0.

完整代码

class Solution {
    public int maxProfit(int k, int[] prices) {
        int[][] dp = new int[prices.length][2*k+1];
        for (int j = 1; j < 2*k; j+=2) {
            dp[0][j] = -prices[0];
        }
        for (int i = 1; i < prices.length; i++) {
            for (int j = 0; j < 2*k; j+=2) {
                dp[i][j+1] = Math.max(dp[i-1][j+1],dp[i-1][j]-prices[i]);
                dp[i][j+2] = Math.max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]);
            }
        }
        return dp[prices.length-1][2*k];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值