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更新
演算法描述
- 遍歷,計算出第x天之前一次交易可以得到的最大收益,儲存在formmer[n]中
- 遍歷,計算出第x天之後一次交易可以得到的最大收益,儲存在latter[n]中
- 遍歷,計算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