1. 程式人生 > >Leetcode 123 Best Time to Buy and Sell Stock III 至多兩次買賣股票最大收益

Leetcode 123 Best Time to Buy and Sell Stock III 至多兩次買賣股票最大收益

題目描述

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 two transactions.
設計一個演算法來計算最大收益。你至多可以完成兩次交易。

解題思路

這個題可以借鑑第一個題目中的思路。這個題是一個動態規劃的題目。我們假設將1-n天分為1-day,day-n兩部分,然後我們分別在兩部分中至多進行一次交易獲得兩部分的最大值,將兩部分加在一起就是一個待選的最大收益,day可以取1,2,…,n,所以會得到n個後選值,在候選值中選出最大的一個就是最大收益。借鑑121中計算最大收益的方法,我們可以在第一次遍歷中計算1-day的最大收益formmer[n],第二遍歷時計算day-n的最大收益latter[n],最後再遍歷一次得到最大收益max。

公式:

max=max<formmer[i]+latter[i]?fommer[i]+latter[i]:max

這裡需要說明的是,如果formmer[i]和latter[i]的值在計算的時候都用到了第i天的價格,即第i天賣出了股票才的到了formmer[i],第i天買入了股票才得到了latter[i],也並不妨礙我們的計算,因為這就相當於第i天沒有買入和賣出,即所有時間內只進行了以此買賣,而不是兩次。

ps: 2015年小米春季實習生招聘線上筆試第二題就是這個題,不過當時我沒刷這個題,但是還是做出來啦~

發現一個更牛逼的方法,時間複雜度O(n),空間複雜度O(1)。

2015/8/12更新

演算法描述

  1. 遍歷,計算出第x天之前一次交易可以得到的最大收益,儲存在formmer[n]中
  2. 遍歷,計算出第x天之後一次交易可以得到的最大收益,儲存在latter[n]中
  3. 遍歷,計算formmer[i] + latter[i] 得到最大收益max

程式碼 C

/**
 * 計算最大收益
 * @param prices : 每日價格
 * @param pricesDize : 資料規模
 * @return : 最大收益 
 * @note : 至多進行兩次買賣
 */
int maxProfit(int* prices, int
pricesSize) { /* 如果價格資料為空或只有一個數據,返回0 */ if (pricesSize <= 1) return 0; int *maxProfitDuringFormmerDays = (int *)malloc(sizeof(int) * pricesSize), *maxProfitDuringLatterDays = (int *)malloc(sizeof(int) * pricesSize); int day, diff, minPrice, maxPrice, maxProfit; /* 計算某一天極其之前所有時間內的最大利益 */ minPrice = *prices; maxProfit = 0; *maxProfitDuringFormmerDays = 0; for (day = 1; day < pricesSize; ++day) { diff = *(prices + day) - minPrice; if (diff < 0) minPrice = *(prices + day); else if (diff > maxProfit) maxProfit = diff; *(maxProfitDuringFormmerDays + day) = maxProfit; } /* 計算某一天極其之後所有時間內價格的最利益 */ maxPrice = *(prices + pricesSize - 1); maxProfit = 0; *(maxProfitDuringLatterDays + pricesSize - 1) = 0; for (day = pricesSize - 2; day > -1; --day) { diff = maxPrice - *(prices + day); if (diff < 0) maxPrice = *(prices + day); else if (diff > maxProfit) maxProfit = diff; *(maxProfitDuringLatterDays + day) = maxProfit; } /* 計算最大收益 */ int sum; maxProfit = 0; for (day = 0; day < pricesSize; ++day) { sum = *(maxProfitDuringFormmerDays + day) + *(maxProfitDuringLatterDays + day); if (sum > maxProfit) maxProfit = sum; } free(maxProfitDuringFormmerDays); free(maxProfitDuringLatterDays); return maxProfit; }

程式碼 CPP

class Solution {
public:
    /**
     * 計算最大收益
     * @param prices : 每日價格
     * @return : 最大收益 
     * @note : 至多進行兩次買賣
     */
    int maxProfit(vector<int>& prices) {
        int pricesSize = prices.size();

        /* 如果價格資料為空或只有一個數據,返回0  */
        if (pricesSize <= 1) return 0;

        vector<int> maxProfitDuringFormmerDays(pricesSize),
                maxProfitDuringLatterDays(pricesSize);

        int day, diff, minPrice, maxPrice, maxProfit;

        /* 計算某一天極其之前所有時間內的最大利益  */
        minPrice = prices[0]; 
        maxProfit = 0;
        maxProfitDuringFormmerDays[0] = 0;
        for (day = 1; day < pricesSize; ++day) {
            diff = prices[day] - minPrice;
            if (diff < 0) minPrice = prices[day];
            else if (diff > maxProfit) maxProfit = diff;
            maxProfitDuringFormmerDays[day] = maxProfit;
        }

        /* 計算某一天極其之後所有時間內價格的最利益  */
        maxPrice = prices[pricesSize - 1];
        maxProfit = 0;
        maxProfitDuringLatterDays[pricesSize - 1] = 0;
        for (day = pricesSize - 2; day > -1; --day) {
            diff = maxPrice - prices[day];
            if (diff < 0) maxPrice = prices[day];
            else if (diff > maxProfit) maxProfit = diff;
            maxProfitDuringLatterDays[day] = maxProfit;
        }

        /* 計算最大收益 */
        int sum;
        maxProfit = 0;
        for (day = 0; day < pricesSize; ++day) {
            sum = maxProfitDuringFormmerDays[day] + maxProfitDuringLatterDays[day];
            if (sum > maxProfit) maxProfit = sum;
        }

       return maxProfit;
    }

};

執行情況

Lauguage Status Time
c Accept 4ms
cpp Accept 12ms

2015/7/8