1. 程式人生 > >LeetCode-【陣列】- 買賣股票的最佳時機含手續費

LeetCode-【陣列】- 買賣股票的最佳時機含手續費

給定一個整數陣列 prices,其中第 i 個元素代表了第 i 天的股票價格 ;非負整數 fee 代表了交易股票的手續費用。

你可以無限次地完成交易,但是你每次交易都需要付手續費。如果你已經購買了一個股票,在賣出它之前你就不能再繼續購買股票了。

返回獲得利潤的最大值。

示例 1:

輸入: prices = [1, 3, 2, 8, 4, 9], fee = 2
輸出: 8
解釋: 能夠達到的最大利潤:  
在此處買入 prices[0] = 1
在此處賣出 prices[3] = 8
在此處買入 prices[4] = 4
在此處賣出 prices[5] = 9
總利潤: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

注意:

  • 0 < prices.length <= 50000.
  • 0 < prices[i] < 50000.
  • 0 <= fee < 50000.

題解:選擇的關鍵是找到一個最大後是不是能夠賣掉stock,重新開始尋找買入機會。比如序列1 3 2 8,如果發現2小於3就完成交易買1賣3,此時由於fee=2,(3-1-fee)+(8-2-fee)<(8-1-fee),所以說明賣早了,令max是當前最大price,當(max-price[i]>=fee)時可以在max處賣出,且不會存在賣早的情況,再從i開始重新尋找買入機會。

貪心解法:

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n=prices.length;
        if(n<=1)
            return 0;
        int p=0,curP=0;
        int minP=prices[0],maxP=prices[0];
        for(int i=1;i<n;i++){
           minP=Math.min(minP,prices[i]);
           maxP=Math.max(maxP,prices[i]);
           curP=Math.max(curP,prices[i]-minP-fee);
           if(maxP-prices[i]>=fee){
               p+=curP;
               curP=0;
               maxP=prices[i];
               minP=prices[i];
           }
        }
        return p+curP;
    }
}

題解:動態轉移點:手上有沒有股票 進行DP。對於第i天的最大收益,應分成兩種情況,一是該天結束後手裡沒有stock,可能是保持前一天的狀態也可能是今天賣出了,此時令收益為cash;二是該天結束後手中有一個stock,可能是保持前一天的狀態,也可能是今天買入了。由於第i天的情況只和i-1天有關,所以用兩個變數cash和buy就可以,不需要用陣列

動規解法:

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