[Leetcode] 188. Best Time to Buy and Sell Stock IV 解题报告

题目

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

思路

这道题目自己没有独立做出来,我在网上参考了两种最好的解法,这里和大家分享。

1、记录局部最优解和全局最优解的动态规划法:用local[i][j]表示到达第i天时,最多进行j次交易的局部最优解;用global[i][j]表示到达第i天时,最多进行j次交易的全局最优解。它们两者的关系如下(其中diff = prices[i] - prices[i - 1]):

local[i][j] = max(global[i-1][j-1] + max(diff, 0),  local[i-1][j] + diff);

global[i][j] = max(global[i-1][j], local[i][j]);

其中的local[i-1][j] + diff就是为了避免第i天交易和第i-1天交易合并成为一次交易而少一次交易收益。算法的时间复杂度是O(n^2),空间复杂度也是O(n^2)。不过由于local和global的递推公式只和它临近的元素有关,所以目测空间复杂度还可以进一步降低到O(n)。这里偷个懒,不弄了。

2、记录买入卖出的动态规划法:可以记录k次交易每次买入之后和卖出之后最大的利润。第i次买操作买下当前股票之后剩下的最大利润为第(i-1)次卖掉股票之后的利润 - 当前的股票价格,状态转移方程为:buys[i] = max(sells[i - 1] - current_price, buys[i]). 第i次卖操作卖掉当前股票之后剩下的最大利润为第i次买操作之后剩下的利润 + 当前的股票价格。状态转移方程为:sells[i] = max(buys[i] + current_price, sells[i])。最终所求即为sells[k]。

代码

1、记录局部最优解和全局最优解的动态规划法:

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(prices.size() < 2) {
            return 0;
        }
        int days = prices.size();
        if(k >= days / 2) {
            return maxProfit(prices);
        }
        vector<vector<int>> local(days, vector<int>(k + 1, 0));
        vector<vector<int>> global(days, vector<int>(k + 1, 0));
        for(int i = 1; i < days; ++i) {
            int diff = prices[i] - prices[i - 1];
            for(int j = 1; j <= k; ++j) {
                local[i][j] = max(global[i-1][j-1], local[i-1][j] + diff);
                global[i][j] = max(global[i-1][j], local[i][j]);
            }
        }
        return global[days - 1][k];
    }
private:
    int maxProfit(vector<int>& prices) {
        int max_profit = 0;
        for(int i = 1; i < prices.size(); ++i) {
            if(prices[i] > prices[i-1]) {
                max_profit += prices[i] - prices[i-1];
            }
        }
        return max_profit;
    }
};
2、记录买入卖出的动态规划法:

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(prices.size() < 2) {
            return 0;
        }
        int days = prices.size(), ret = 0;
        if(k >= days / 2) {
            return maxProfit(prices);
        }
        vector<int> buys(days + 1, INT_MIN);
        vector<int> sells(days + 1, 0);
        for (int i = 0; i < days; ++i) {
            for (int j = 1; j <= k; ++j) {
                buys[j] = max(sells[j - 1] - prices[i], buys[j]);
                sells[j] = max(buys[j] + prices[i], sells[j]);
            }
        }
        return sells[k];
    }
private:
    int maxProfit(vector<int>& prices) {
        int max_profit = 0;
        for(int i = 1; i < prices.size(); ++i) {
            if(prices[i] > prices[i-1]) {
                max_profit += prices[i] - prices[i-1];
            }
        }
        return max_profit;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值