问题描述:
Say you have an array for which the ith element is the price of a given stock on day i.
给你一个数组,里边的第i个元素存储的是股票在第i天的价格
Design an algorithm to find the maximum profit. You may complete at most k transactions.
允许最多完成k次交易(买进卖出k次),设计算法找出最大收益。
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
不能同时进行多次交易(在你再一次买进之前必须先卖出)。
问题求解:
特殊动态规划法。传统的动态规划我们会这样想,到第i天时进行j次交易的最大收益,要么等于到第i-1天时进行j次交易的最大收益(第i天价格低于第i-1天的价格),要么等于到第i-1天时进行j-1次交易,然后第i天进行一次交易(第i天价格高于第i-1天价格时)。于是得到动规方程如下(其中diff = prices[i] – prices[i – 1]):
profit[i][j] = max(profit[i – 1][j], profit[i – 1][j – 1] + diff)
看起来很有道理,但其实不对,为什么不对呢?因为diff是第i天和第i-1天的差额收益,如果第i-1天当天本身也有交易呢,那么这两次交易就可以合为一次交易,这样profit[i – 1][j – 1] + diff实际上只进行了j-1次交易,而不是最多可以的j次,这样得到的最大收益就小了。
那么怎样计算第i天进行交易的情况的最大收益,才会避免少计算一次交易呢?我们用一个局部最优解和全局最有解表示到第i天进行j次的收益,这就是该动态规划的特殊之处。
定义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])
局部最优值是比较前一天并少交易一次的全局最优加上大于0的差值,和前一天的局部最优
加上差值后相比,两者之中取较大值,而全局最优比较局部最优和前一天的全局最优。
其中的local[i – 1][j] + diff就是为了避免第i天交易和第i-1天交易合并成一次交易而少一次交易收益。
参考:
http://www.cnblogs.com/grandyang/p/4295761.html
http://www.cnblogs.com/grandyang/p/4295761.html
代码:时间O(n),空间O(k)。
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if(n <= 1){
return 0;
}
//k大于天数时,退化成Best Time to Buy and Sell Stock II问题
if(k >= n){
return maxProfit2(prices);
}
vector<int> local(k+1);
vector<int> global(k+1);
//两层for循环实现二维数组,比如global[i][j]
//可由i循环下的global[j]实现
for(int i=1;i<n;i++){
int diff = prices[i] - prices[i-1];
for(int j=k;j>0;j--){
local[j]=max(global[j-1]+max(diff,0),local[j]+diff);
global[j]=max(global[j],local[j]);
}
}
return global[k];
}
int maxProfit2(vector<int>& prices){
int n = prices.size();
int profit=0;
int max_profit=0;
for(int i=1;i<n;i++){
if(prices[i] > prices[i-1]){
profit=prices[i]-prices[i-1];
max_profit += profit;
}
}
return max_profit;
}
};