https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
这是leecode上的一道题,主要利用动态规化解,关键是找到状态转移方程:
设:[1,2,3,0,2],选定一天为是否卖出股票。
状态转移方程为:F[i]=max(buy_and_sell(k,i)+F[k-2] | k=i-1..0, F[i-1])。F[i]代表第i天卖出的最大收益,buy_and_sell(k,i)代表从k天买入并在i天卖出的收益,同时若是k天买入,那入之前的最大收益肯定是F[k-2]。
代码如下:
int max(int a,int b){
if(a < b){
return b;
}
return a;
}
int buysell(int* prices, int buyday,int sellday){
if(prices[sellday] > prices[buyday]){
return prices[sellday] - prices[buyday];
}
return 0;
}
int maxProfit(int* prices, int pricesSize){
int i;
int maxvalue;
int today,buyDay;
if(pricesSize <=1){
return 0;
}
int *MaxProfitData = malloc(pricesSize * sizeof(prices[0]));
if(MaxProfitData == NULL){
return 0;
}
MaxProfitData[0] = 0;
for(today=1;today<pricesSize;today++){
maxvalue = 0;
for(buyDay=today-1;buyDay>=0;buyDay--){
int value = buysell(prices,buyDay,today);
if(buyDay >=2)
value += MaxProfitData[buyDay-2];
if(maxvalue < value){
maxvalue = value;
}
}
MaxProfitData[today] = max(maxvalue,MaxProfitData[today-1]);
}
maxvalue = MaxProfitData[pricesSize-1];
free(MaxProfitData);
return maxvalue;
}
F[i]=max(buy_and_sell(k,i),F[k-2]|k=0...i-1 , F[i-1])事实上并不需要k从0...i-1完全遍历,因为出现最大收益只可能出现上一次F[i-1]时的最早买入时间至i之间,并不需要考虑之前的。通过记录上一次的买入时间,优化之后代码如下:
int max(int a,int b){
if(a < b){
return b;
}
return a;
}
int buysell(int* prices, int buyday,int sellday){
if(prices[sellday] > prices[buyday]){
return prices[sellday] - prices[buyday];
}
return 0;
}
int maxProfit(int* prices, int pricesSize){
int i;
int maxvalue;
int today,buyDay;
if(pricesSize <=1){
return 0;
}
int *MaxProfitData = malloc(pricesSize * sizeof(prices[0]));
if(MaxProfitData == NULL){
return 0;
}
int *MaxProfitBuyDay = malloc(pricesSize * sizeof(prices[0]));
if(MaxProfitBuyDay == NULL){
return 0;
}
MaxProfitData[0] = 0;
MaxProfitBuyDay[0] = 0;
for(today=1;today<pricesSize;today++){
maxvalue = 0;
int maxvalue_buyday = 0;
for(buyDay=today-1;buyDay>=MaxProfitBuyDay[today-1];buyDay--){
int value = buysell(prices,buyDay,today);
if(buyDay >=2)
value += MaxProfitData[buyDay-2];
if(maxvalue < value){
maxvalue = value;
maxvalue_buyday = buyDay;
}
}
MaxProfitData[today] = max(maxvalue,MaxProfitData[today-1]);
if(maxvalue > MaxProfitData[today-1]){
MaxProfitBuyDay[today] = maxvalue_buyday;
}else{
MaxProfitBuyDay[today] = MaxProfitBuyDay[today-1];
}
}
maxvalue = MaxProfitData[pricesSize-1];
free(MaxProfitData);
free(MaxProfitBuyDay);
return maxvalue;
}