leetcode 188---Best Time to Buy and Sell Stock IV

来源:互联网 发布:红帽linux是什么 编辑:程序博客网 时间:2024/05/22 04:50

问题描述:

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;    }};
0 0
原创粉丝点击