1. 程式人生 > >LeetCode 123 :Best Time to Buy and Sell Stock III

LeetCode 123 :Best Time to Buy and Sell Stock III

   該問題和121,122是一類問題,難度逐層遞增,首先先考慮121題

   

  只能交易一次,尋找最大利潤,一開始想到的最簡單的策略就是用一個值儲存目前為止碰到的最小進價,和當前值相減後與當前最大利潤比較,這樣只需要兩個額外變數即可,但是這樣8ms只能打敗30%的答案。

 

  對於122題:

    放寬了限制,可以進行無數次的交易,總利潤最大就行,這時想到的一個最佳策略就是用一個數組表示和前一天相比的淨利潤,最後將陣列中所有非負值相加即可。這樣能夠打敗98%的答案。

 

針對123題,瞬間懵逼,要求能夠進行兩次交易,第一個想到的無非就是嘗試DP,但是狀態轉移方程遲遲無法找到。。參考別人的思路後,原來該類問題可以利用狀態機的方式進行解決,對於123題,可以設定4種狀態,狀態一 是第一次交易還沒開始,可以選擇的策略是繼續保持或者進第一個貨,狀態二 是第一次交易還沒有結束,以此類推。

  方法如下:

class Solution {
public:
    


    
    int maxProfit(vector<int>& prices) {
        
        if(prices.size()<2) return 0;
        
        int s1=-prices[0],s2=INT_MIN,s3=INT_MIN,s4=INT_MIN;
        
        for(int i=1;i<prices.size();i++)
        {
            s1=max(s1,-prices[i]);
            s2=max(s2,s1+prices[i]);
            s3=max(s3,s2-prices[i]);
            s4=max(s4,s3+prices[i]);
        }
        
        return s4;
        
        
    }
};

 

  輕輕鬆鬆幹掉99%的答案,同樣可以將這種思路用到前面兩題

 

  對於121,狀態機只有兩種狀態

    

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        
        if(prices.size()<2) return 0;
        int s1=-prices[0],s2=INT_MIN;
        
        
        for(auto c:prices)
        {
            s1=max(s1,-c);
            s2=max(s2,s1+c);
        }
        return s2;
        
    }
};

 

對於122,是不是又感覺懵逼了,交易可以有無數次,這時可以考慮狀態一和狀態二的一個閉環

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        
        if(prices.size()==0) return 0;
        int s1=-prices[0],s2=0;
        for(auto c:prices)
        {
            s1=max(s1,s2-c);
            s2=max(s2,s1+c);
        }
        
        return s2;
    }
};

 

這樣就解決了無數次的問題,對於該類問題都可以使用這類方法解決。