[leetcode]Best Time to Buy and Sell Stock 系列

  1. Best Time to Buy and Sell Stock
    reqest:只允許購買一次股票萧芙,即只能買入賣出一次

構建類似馬爾科夫鏈的轉態(tài)轉移函數:
每個交易日可以又兩種選擇 buy 和sell
而buy和sell之間存在著先后關系清寇,buy為第一次買入得到的最大利潤,一定是負值梯皿,sell為第一次賣出得到的最大利潤。

buy(i)=Math.max(buy(i-1),-prices[i]);
//實質是保存目前為止的最小交易值
sell(i)=Math.max(sell(i-1),buy(i-1)+prices[i]);
//在不斷更新最小交易值的同時,不斷判斷目前交易天賣出是否是最大值隐圾。
必須先更新sell值望几,再更新buy,目的是為了利用上次迭代的buy去更新sell值
class Solution {
    public int maxProfit(int[] prices) {
        int buy=Integer.MIN_VALUE;
        int sell=0;
        int n=prices.length;
        for(int i=0;i<n;i++){
            sell=Math.max(sell,buy+prices[i]);
            buy=Math.max(buy,-prices[i]);
            
        }
        return sell;
        
    }
}
  1. Best Time to Buy and Sell Stock III
    request:可以最多兩次次買入賣出

利用上面的思路绩脆,找狀態(tài)轉移方程,可以寫出

sell2=Math.max(sell2,buy2+prices[i]);
//第二次買出的最大利潤
buy2=Math.max(buy2,sell1-prices[i]);
//第二次買入的最大利潤
sell1=Math.max(sell1,buy1+prices[i]);
//利用目前最大的買入利潤得到第一次賣出的最大利潤
buy1=Math.max(buy1,-prices[i]);
//保存第一次買入的最大利潤橄抹,也就是交易額最小
所有變量是按照轉態(tài)轉移方程去不斷更新優(yōu)化靴迫,獲得最佳值,
  1. Best Time to Buy and Sell Stock II
    requeat:可以多次買入買出楼誓,但每次買入必須在上一次賣出

    如果利用上述思路玉锌,繼續(xù)使用狀態(tài)轉移方程,那么因為交易次數的不確定疟羹,最后得到的無數的狀態(tài)轉移方程主守,不可能實現,那么就要把狀態(tài)轉移方程合并成符合題目要求的樣子
    可以看到在Best Time to Buy and Sell Stock,單次交易的解決方法榄融,那么無數次交易可以看成是無數次單次交易参淫,先找到在某個時刻點買入的股票能連續(xù)獲利的的最大值,一旦哪天賣出是相較上一天是虧本愧杯,則得到了一次買賣的收入涎才,然后再次重復
    其中的關鍵就是連續(xù)獲利,也就是判斷當天交易額是否比上一天高力九,高說明可以持續(xù)獲利耍铜,低則說明買入的股票在上一天得到頂峰,上一天可以賣出跌前,然后在尋找下一個連續(xù)獲利的序列
    與一次買賣最大的區(qū)別在于棕兼,每次賣出獲利不是全局最優(yōu)值,但是無數個局部最優(yōu)值的疊加舒萎,貪婪算法程储。

class Solution {
    public int maxProfit(int[] prices) {
        int min=Integer.MAX_VALUE;
        int max=0;
        int n = prices.length;
        for(int i=1;i<n;i++){
           if(prices[i]>prices[i-1])
               max+=prices[i]-prices[i-1];
        }
        return max;
    }
}

第二種方法臂寝,就是利用狀態(tài)轉移方程章鲤,對每次交易日的兩種選擇判斷執(zhí)行,這里的buy包含兩種意思咆贬,之前賣了败徊,當前天買入,或是之前買入了掏缎,然后一直保持在手里

class Solution {
    public int maxProfit(int[] prices) {
        int min=Integer.MAX_VALUE;
        int max=0;
        int n = prices.length;
        int[] buy=new int[n+1];
        buy[0]=Integer.MIN_VALUE;
        int[] sell=new int[n+1];
        for(int i=1;i<=n;i++){
           sell[i]=Math.max(sell[i-1],buy[i-1]+prices[i-1]);
           buy[i]=Math.max(buy[i-1],sell[i-1]-prices[i-1]);
        }
        return sell[n];
    }
}
  1. Best Time to Buy and Sell Stock IV
    request:
    指定交易次數k,然后求最大利潤皱蹦。

同樣的從一次買賣中尋找線索
二次買賣是在每個交易日更新二次交易值煤杀,那么K次買賣是不是能更新k次交易日,這個思路明顯是正確的沪哺。

class Solution {
    public int maxProfit(int k, int[] prices) {
        int n = prices.length;
        
        if(k==0||n<2)
            return 0;
        if (n/2 < k){
            return quickSolve(prices);
//因為當k次交易大于交易日的一般沈自,也就是每天交易都打不到k次交易,則就可以按照無數次交易貪婪得到無數局部最優(yōu)解的疊加
        }
        int[] hold = new int[k+1];
        for(int i=0;i<=k;i++){
            hold[i]=Integer.MIN_VALUE;
        }

        int[] unhold = new int[k+1];
        hold[1]=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            for(int j=1;j<=k;j++){
                unhold[j]=Math.max(unhold[j],hold[j]+prices[i]);
                hold[j]=Math.max(hold[j],unhold[j-1]-prices[i]);
                
               //在每個交易日對k個買賣的值執(zhí)行更新
                
            }
        }
        return unhold[k];
    }
    int quickSolve(int[] prices) {
        int len = prices.length, profit = 0;
        for (int i = 1; i < len; i++)
            // as long as there is a price gap, we gain a profit.
            if (prices[i] > prices[i - 1]) profit += prices[i] - prices[i - 1];
        return profit;
    }

}
  1. Best Time to Buy and Sell Stock with Cooldown
    request:可以多次交易辜妓,但是在賣出之后又一天的冷凍期不能買入
    同樣利用狀態(tài)轉移方程枯途,
    public int maxProfit(int[] prices) {
        /*
            重點在于表述狀態(tài)轉移方程,也就是從遞歸的角度描述籍滴,然后反向執(zhí)行
            首先股票包含的狀態(tài)為sell buy cool
            從遞歸的角度來看:
                股票在第i天能夠執(zhí)行的操作有 buy sell ,并且在賣和買之間有一天的cool,但是在買和賣之間同樣存在隱藏的cool_hidden;
                判斷第i天四種操作獲取的最大利潤
                buy[i]:cool[i-1]-price[i];
                cool_hidden[i]:cool_hidden[i-1];buy[i-1];
                sell[i]:cool_hidden[i-1]+price[i];buy[i-1]+price[i];
                cool[i]:sell[i-1];cool[i-1];
                這個狀態(tài)太長酪夷,開始降維合并:
                首先,cool_hidden 可以合并到buy:hold操作就包含了buy和cool_hidden;
                cool也可以列合并到sell:unhold操作包含sell和cool

                hold[i]=max(hold[i-1],unhold[i-2]-price[i]);
                unhold[i]=max(unhold[i-1],hold[i-1]+price[i]);
        */
        int n = prices.length;
        if(n<2)
            return 0;
        int[] hold=new int[n];
        int[] unhold=new int[n];
        hold[0]=-prices[0];
        unhold[0]=0;
        hold[1]=Math.max(hold[0],unhold[0]-prices[1]);
        unhold[1]=Math.max(unhold[0],hold[0]+prices[1]);
        for(int i=2;i<n;i++){
            hold[i]=Math.max(hold[i-1],unhold[i-2]-prices[i]);
            unhold[i]=Math.max(unhold[i-1],hold[i-1]+prices[i]);
        }
        return Math.max(hold[n-1],unhold[n-1]);
                     
    }                     
}
6. Best Time to Buy and Sell Stock with Transaction Fee
request:每筆交易需要手續(xù)費孽惰,但不限交易次數

class Solution {
public int maxProfit(int[] prices, int fee) {
int n = prices.length;
int[] hold = new int[n];
int[] unhold=new int[n];
unhold[0]=0;
hold[0]=-prices[0];
for(int i=1;i<n;i++){
unhold[i]=Math.max(unhold[i-1],hold[i-1]+prices[i]-fee);
hold[i]=Math.max(hold[i-1],unhold[i-1]-prices[i]);
}
return unhold[n-1];
}
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末晚岭,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子勋功,更是在濱河造成了極大的恐慌坦报,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酝润,死亡現場離奇詭異燎竖,居然都是意外死亡,警方通過查閱死者的電腦和手機要销,發(fā)現死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夏块,“玉大人疏咐,你說我怎么就攤上這事∑旯” “怎么了浑塞?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長政己。 經常有香客問我酌壕,道長,這世上最難降的妖魔是什么歇由? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任卵牍,我火速辦了婚禮,結果婚禮上沦泌,老公的妹妹穿的比我還像新娘糊昙。我一直安慰自己,他們只是感情好谢谦,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布释牺。 她就那樣靜靜地躺著萝衩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪没咙。 梳的紋絲不亂的頭發(fā)上猩谊,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機與錄音祭刚,去河邊找鬼牌捷。 笑死,一個胖子當著我的面吹牛袁梗,可吹牛的內容都是我干的宜鸯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼遮怜,長吁一口氣:“原來是場噩夢啊……” “哼淋袖!你這毒婦竟也來了?” 一聲冷哼從身側響起锯梁,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤即碗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后陌凳,有當地人在樹林里發(fā)現了一具尸體剥懒,經...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年合敦,在試婚紗的時候發(fā)現自己被綠了初橘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡充岛,死狀恐怖保檐,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情崔梗,我是刑警寧澤夜只,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站蒜魄,受9級特大地震影響扔亥,放射性物質發(fā)生泄漏。R本人自食惡果不足惜谈为,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一旅挤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧峦阁,春花似錦谦铃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘪菌。三九已至,卻和暖如春嘹朗,著一層夾襖步出監(jiān)牢的瞬間师妙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工屹培, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留默穴,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓褪秀,卻偏偏與公主長得像蓄诽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子媒吗,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內容