188. 买卖股票的最佳时机 IV

✅做题思路or感想

股票问题 + 找规律,找到规律后就很简单了

顺便一说,一次交易包括一次卖出和买入!!!故这里总的交易次数是2 * k

dp数组含义

dp[i][j]:第i天第j次交易持有股票的状态

dp[i][j + 1]:第i天第j次交易没有股票的状态

推导公式

不如来看一下k = 2时的递推公式

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

故知,除了第一次交易,其余时候都遵循着规律

故有

if (j == 0) {	//除了第一次买股票有点特殊
    dp[i][j] = max(dp[i - 1][j], -prices[i]);
    dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] + prices[i]);
} else {	//其余皆是规律
    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
    dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] + prices[i]);
}

初始化

下面是k = 2时的初始化

dp[0][0] = -prices[0];	//第一天就买了股票
dp[0][1] = 0;	//第一天什么也没干
dp[0][2] = -prices[0];	//第一条买了又卖了后,又买了
dp[0][3] = 0;	//第一天买了又卖了,然后又买了又卖了

故由规律得本题的初始化

for (int j = 0; j < 2 * k; j += 2) {
    dp[0][j] = -prices[0];
    dp[0][j + 1] = 0;
}

遍历顺序

从小推大,所以是正序

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if (prices.size() == 0 || k == 0)return 0;	//这里谨防奇怪非法用例
        vector<vector<int>>dp (prices.size() + 1, vector<int>(k * 2 + 1, 0));
        //j是持有股票,j + 1是没有股票、
        //这里区块化的管理就在for下功夫就好了,用j += 2来区块化管理
        for (int j = 0; j < 2 * k; j += 2) {	
            dp[0][j] = -prices[0];
            dp[0][j + 1] = 0;
        }
        for (int i = 1; i < prices.size(); i++) {
            for (int j = 0; j < 2 * k; j += 2) {
                if (j == 0) {
                    dp[i][j] = max(dp[i - 1][j], -prices[i]);
                    dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] + prices[i]);
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
                    dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] + prices[i]);
                }
            }
        }
        return dp[prices.size() - 1][2 * k - 1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值