LeetCode 188. Best Time to Buy and Sell Stock IV

Say you have an array for which the ith
element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most k transactions.
Note:You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Credits:Special thanks to @Freezen for adding this problem and creating all test cases.
Subscribe to see which companies asked this question.


假設(shè)你有一個(gè)數(shù)組,它的第i個(gè)元素是一支給定的股票在第i天的價(jià)格。
設(shè)計(jì)一個(gè)算法來找到最大的利潤(rùn)。你最多可以完成 k 筆交易。
樣例
給定價(jià)格 = [4,4,6,1,1,4,2,5], 且 k = 2, 返回 6.

solution

典型的動(dòng)態(tài)規(guī)劃,并且利用局部和全局最優(yōu),這種思想值得仔細(xì)體會(huì),好好掌握。
這種局部最優(yōu)與全局最優(yōu)問題
global[i][j] = max(local[i][j], global[i - 1][j])
很容易知道上面這個(gè)遞推式。
關(guān)鍵在于求取局部最優(yōu)的遞推式,在本題中
local[i][j] = max(global[i - 1][j - 1] + max(diff, 0), local[i - 1][j] + diff)
這里我們需要兩個(gè)遞推公式來分別更新兩個(gè)變量local和global
我們定義local[i][j]為在到達(dá)第i天時(shí)最多可進(jìn)行j次交易并且最后一次交易在最后一天賣出的最大利潤(rùn),此為局部最優(yōu)。然后我們定義global[i][j]為在到達(dá)第i天時(shí)最多可進(jìn)行j次交易的最大利潤(rùn),此為全局最優(yōu)
局部最優(yōu)解的遞推式可以這樣理解:

  • 在i-1天時(shí),正在進(jìn)行第j次交易,所以我們最后一天必須將股票賣出,而且這是算在第j次交易當(dāng)中的,這種情況下,local[i - 1][j] + diff,只需將i-1天的局部最優(yōu)解加上最后一天賣出的差值即可,相當(dāng)于將最后一次交易多延遲了一天
  • 第二種情況,就是在第i-1天進(jìn)行j-1次交易的全局最優(yōu)解,我們?cè)谧詈笠惶爝€得進(jìn)行一次交易,必須賣出,如果diff大于0,那么就在第i-1天買進(jìn),i天賣出,如果小于0,就直接在第i天買進(jìn)又賣出,只是為了滿足j次交易,就相當(dāng)于沒有交易,即加上0就可以了。
    這道題還有一個(gè)陷阱,可以優(yōu)化的地方,就是如果k>=prices.length/2。那我們可以理解可以進(jìn)行任意次交易了,因?yàn)橛行Ы灰锥夹枰獌商靵硗瓿?,所以直接使用貪心法就可以算出來了?/li>
public int maxProfit(int k, int[] prices) {
        int len = prices.length;
        if(k <=0 || len < 2)
            return 0;
        int maxProfit = 0;
        
        if(k >= len/2) {
            //直接當(dāng)作貪心處理,也就是問題2的答案
            for(int i=1;i<len;i++) {
                int diff = prices[i]-prices[i-1];
                if(diff > 0)
                    maxProfit += diff;
            }
            return maxProfit;
        }
        
        int[][] local = new int[len][k+1];
        int[][] global = new int[len][k+1];
        
        for(int i=1;i<len;i++) {
            int diff = prices[i] - prices[i-1];
            for(int j=1;j<=k;j++) {
                local[i][j] = Math.max(global[i-1][j-1] + Math.max(diff, 0), 
                        local[i-1][j] + diff);
                global[i][j] = Math.max(local[i][j], global[i-1][j]);
            }
        }
        return global[len-1][k];
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容