算法刷题打卡043 | 动态规划11

继续进行买卖股票系列~

LeetCode 123 买卖股票的最佳时机III

题目链接:123. 买卖股票的最佳时机 III - 力扣(Leetcode)

买卖股票的第三个版本同样是在买卖次数上做文章,强调最多能交易两次,也就是买入卖出各两次,同样要求买入前必须保证手里没有持有。如果沿用买卖股票I和II的做法,就无法确定dp推导过程中的交易次数。因此需要重新进行状态定义,状态从股票持有变为交易状态,分别记录每一天如果为第一次买入、第一次卖出、第二次买入、第二次卖出时的最大利润,可以保证买入卖出的先后顺序。

确定状态后,状态推导和初始化就比较容易想到了。第一次买入前没有交易,因此要么延续前一天的状态,要么在当天在利润为0的情况下买入,而第一次卖出必须在第一次买入的基础上进行,其他状态的分析类似。两次买入的初始状态均为在第0天买入花费的prices[0],而卖出可以是在买入的同一天卖出,因此可以初始化为0。因为是最多两次交易,获得最大利润时可能只进行了一次交易,因此返回后一天两次卖出中较大的利润作为最终结果。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        int buy1 = -prices[0], sell1 = 0;
        int buy2 = -prices[0], sell2 = 0;

        for (int i = 1; i < len; ++i) {
            buy1 = max(buy1, -prices[i]);
            sell1 = max(sell1, buy1 + prices[i]);
            buy2 = max(buy2, sell1 - prices[i]);
            sell2 = max(sell2, buy2 + prices[i]);
        }
        return sell2;
    }
};

 上述代码直接进行了空间复杂度优化,时间和空间复杂度分别是O(n)和O(1)。

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

题目链接:188. 买卖股票的最佳时机 IV - 力扣(Leetcode)

 这一题和III其实异曲同工,相当于先用两次交易打个底,拓展到k次就比较简单了。最多可以进行k次交易,因此状态有2k个,记录每一天第k次买入或卖出可以获得的最大利润,通过一次内层循环依次更新每个状态即可。买入的状态均初始化为-prices[0],卖出的状态均初始化为0,时间和空间复杂度分别是O(kn)和O(k)。

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size();
        vector<int> buys(k, -prices[0]);
        vector<int> sells(k, 0);
        for(int i=1; i < n; i++){
            for(int j=0; j < k; j++){
                if(j==0) buys[j] = max(buys[j], - prices[i]);
                else buys[j] = max(buys[j], sells[j-1] - prices[i]);
                sells[j] = max(sells[j], buys[j] + prices[i]);
            }
        }
        return sells[k-1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值