【LeetCode刷题笔记-50 188:买卖股票的最佳时机IV】

题目:
在这里插入图片描述
这次的题和上次计算股票最大利润的题目本质上用的算法是一样的。之前已经解释过为什么不能用贪心了,因为有可能你这次卖掉之后无法得到最大利润值,比如1 4 2 9这个序列,假如只能交易一次,贪心会在4卖掉,但是为了求极大利润应该在9卖掉。

所以这种题基本都是使用动态规划解决的。

我们根据题解的思路来好了。

使用buy【i】【j】记录对于数组prices【0…i】进行j次交易,并且当前手上持有股票,可以获得的最大利润。

同理,用sell【i】【j】表示不持有股票的最大利润。

于是:

buy【i】【j】 = max{buy【i-1】【j】,buy【i-1】【j】-prices【i】}
sell 【i】【j】 = max{sell【i-1】【j】,sell【i-1】【j-1】+prices【i】}

因为卖出是计算交易次数的,所以j要减一(因为我们假定是在卖出的时候记作一次交易,当然也可以设定在买入的时候,只不过代码写法不一样)

然后注意初始化sell和buy【0】【1…k】为比较小的值即可。然后对于每一个i二重循环不断转移状态即可。

C++代码(附带测试)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if (prices.empty()) {//如果没有股票,返回0 
            return 0;
        }

        int n = prices.size();
		//令n等于prices的大小,这点很重要。因为size()返回的是无符号整数,所以不能有size()-1之类的运算 
		 
        k = min(k, n / 2);//n天最多只能进行n/2场交易 
        vector<vector<int>> buy(n, vector<int>(k + 1));
        vector<vector<int>> sell(n, vector<int>(k + 1));

        buy[0][0] = -prices[0];
        sell[0][0] = 0;
        for (int i = 1; i <= k; ++i) {//初始化 
            buy[0][i] = sell[0][i] = INT_MIN / 2;
        }

        for (int i = 1; i < n; ++i) {
            buy[i][0] = max(buy[i - 1][0], sell[i - 1][0] - prices[i]);//在j等于0的时候,sell保持为0,因为j-1不合法,即不会出现这样的数字 
            for (int j = 1; j <= k; ++j) {//状态转移运算
				//转移方程 
                buy[i][j] = max(buy[i - 1][j], sell[i - 1][j] - prices[i]);
                sell[i][j] = max(sell[i - 1][j], buy[i - 1][j - 1] + prices[i]);   
            }
        }

        return *max_element(sell[n - 1].begin(), sell[n - 1].end());
        //最后一天一定不持有股票,返回k次交易内最大的利润值即可
    }
};

int main()
{
	int k = 2;
	vector<int> prices = {3,2,6,5,0,3};
	Solution s;
	cout<<s.maxProfit(k,prices)<<endl;
}

PS:代码里面有一个小细节需要注意。

令n等于prices的大小,这点很重要。因为size()返回的是无符号整数,所以不能有size()-1之类的运算,一不小心<0就会自动转成最大的无符号整数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值