leetcode-188. 买卖股票的最佳时机 IV
股票交易问题(动态规划)
题目详情
给定一个整数数组 prices
,它的第 i
个元素 prices[i]
是一支给定的股票在第 i
天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k
笔交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例1:
输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例2:
输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
思路:
1.若k * 2 >= days
我们买入卖出需要至少两天时间,所以如果是这种情况,我们直接利用贪心即可,一有利润就卖出,这样所求得的总利润最大
2.若k * 2 < days
在这种情况下,情况相对复杂,我们可以利用两个dp数组buy
sell
,buy[j]
用来记录在第j
次买入的最大利润,sell[j]
用来记录在第j
次卖出的最大利润
我的代码:
class Solution
{
public:
//辅函数(买入后有利润就卖出---贪心)
int maxProfitUnlimited(vector<int> prices)
{
int maxProfit = 0;
for (int i = 1; i < prices.size(); ++i)
{
if (prices[i] > prices[i-1])
maxProfit += prices[i] - prices[i-1];
}
return maxProfit;
}
//主函数
int maxProfit(int k, vector<int>& prices)
{
int days = prices.size();
if (days < 2) return 0;
if (k * 2 >= days) //情况一直接贪心
return maxProfitUnlimited(prices);
vector<int> buy(k + 1, INT_MIN), sell(k + 1, 0);
//遍历每天的股票价格
for (int i = 0; i < days; ++i)
{
//该天的股票以第j次买入卖出
for (int j = 1; j <= k; ++j)
{
//更新(分析第j次是买入还是卖出)
/* 为了求buy[j](作为第j次是/否买入的最大利润,说明j-1次是卖出的,本次我们只能选择不操作或者买入)
括号里的buy[j]的意思是没有将该天的股票作为第j次买入(第j次买入的是其他的股票),即不操作
如果该天确定买入,此时手里的钱是sell[j-1](第j-1次卖出过的最佳状态) - prices[i](买入价格)
*/
buy[j] = max(buy[j], sell[j-1] - prices[i]);
/*为了求sell[j](作为第j次是/否卖出的最大利润,说明j-1次是买入的,本次我们选择不操作或者卖出)
同理括号里的sell[j]的意思是不操作
如果该天确定卖出,此时手里的钱是buy[j](第j次买入的最佳状态) + prices[i](卖出价格)
*/
sell[j] = max(sell[j], buy[j] + prices[i]);
}
}
return sell[k];
}
};
本题我迷糊的点是:
for循环里,为什么更新buy数组括号里是sell[j-1]
而更新sell数组括号里是buy[j]
而不是buy[j-1]
太傻了,因为buy和sell是一一对应的,只有对应的下标(次)先买入,才能卖出
只有存在了buy[j]
,才能取用sell[j]
涉及知识点:
1.动态规划(dp)