只能進行兩次的股票交易
123. Best Time to Buy and Sell Stock III (Hard)
題目描述:
一共只能進行兩次股票交易,求能夠取得的最大利潤。
思路分析:
這道題是Best Time to Buy and Sell Stock的擴展,現在我們最多可以進行兩次交易。我們仍然使用動態規划來完成,事實上可以解決非常通用的情況,也就是最多進行k次交易的情況。
這里我們先解釋最多可以進行k次交易的算法,然后最多進行兩次我們只需要把k取成2即可。我們還是使用“局部最優和全局最優解法”。我們維護兩種量,一個是當前到達第i天可以最多進行j次交易,最好的利潤是多少(global [i] [j]),另一個是當前到達第i天,最多可進行j次交易,並且最后一次交易在當天賣出的最好的利潤是多少(local [i] [j])。下面我們來看遞推式,全局的比較簡單,
global [i] [j]=max(local [i] [j],global [i-1] [j]),
也就是取當前局部最好的,和過往全局最好的中大的那個(因為最后一次交易如果包含當前天一定在局部最好的里面,否則一定在過往全局最優的里面)。對於局部變量的維護,遞推式是
local [i] [j]=max(global [i-1] [j-1]+max(diff,0),local [i-1] [j]+diff),
也就是看兩個量,第一個是全局到i-1天進行j-1次交易,然后加上今天的交易,如果今天是賺錢的話(也就是前面只要j-1次交易,最后一次交易取當前天),第二個量則是取local第i-1天j次交易,然后加上今天的差值(這里因為local [i-1] [j]比如包含第i-1天賣出的交易,所以現在變成第i天賣出,並不會增加交易次數,而且這里無論diff是不是大於0都一定要加上,因為否則就不滿足local [i] [j]必須在最后一天賣出的條件了)。
代碼:
public int maxProfit(int []prices,int k){
if(prices==null||prices.length==0)
return 0;
int []local=new int [3];
int []global=new int [3];
for(int i=0;i<prices.length-1;i++){
int diff=prices[i+1]-prices[i];
for(int j=2;j>=1;j--){
local[j]=Math.max(global[j-1]+(diff>0?diff:0),local[j]+diff);
global[j]=Math.max(local[j],global[j]);
}
}
return global[2];
}
