leetcode刷題記錄(買賣股票的最佳時機系列問題)
開始逐步拾起C++,故以後的刷題,全用python和C++兩種語言實現。
一、買賣股票的最佳時機 I
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
如果你最多隻允許完成一筆交易(即買入和賣出一支股票),設計一個演算法來計算你所能獲取的最大利潤。
注意你不能在買入股票前賣出股票。
示例 1:
輸入: [7,1,5,3,6,4] 輸出: 5 解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。 注意利潤不能是 7-1 = 6, 因為賣出價格需要大於買入價格。
示例 2:
輸入:[7,6,4,3,1] 輸出: 0 解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。
分析:第一題,相對簡單,只能有一次交易。剛看到第一反應可能是遍歷兩次,找出所有的利潤,選個最大的,意料之中,複雜度O(n^2)肯定超時。在一次遍歷中,可以記錄最小值,同時記錄對應的利潤即可。
python實現:
class Solution: def maxProfit(self, prices): """ :type prices: List[int] :rtype: int """ if len(prices)<2: return 0 profit = 0 minprice = prices[0] for i in prices: minprice = min(i,minprice) profit = max(i-minprice,profit) return profit
C++實現:
class Solution { public: int maxProfit(vector<int>& prices) { if (prices.empty()){ return 0; } int profit = 0; int minprice = prices[0]; for (int i = 0;i<prices.size();i++) { minprice = min(prices[i],minprice); profit = max(profit,prices[i]-minprice); } return profit; } };
二、買賣股票的最佳時機 II
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
設計一個演算法來計算你所能獲取的最大利潤。你可以儘可能地完成更多的交易(多次買賣一支股票)。
注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。
示例 1:
輸入: [7,1,5,3,6,4] 輸出: 7 解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。 隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6-3 = 3 。
示例 2:
輸入: [1,2,3,4,5] 輸出: 4 解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接連購買股票,之後再將它們賣出。 因為這樣屬於同時參與了多筆交易,你必須在再次購買前出售掉之前的股票。
示例 3:
輸入: [7,6,4,3,1] 輸出: 0 解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。
分析:不限制交易次數,其實看起來比 I 還要簡單,可以直接一次遍歷,把後一項大於前一項時,兩者差值相加即可。
python實現:
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if not prices:
return 0
temp = prices[0]
profit = 0
for i in prices:
if i > temp:
profit = profit + i - temp
temp = i
return profit
C++實現:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty())
{
return 0;
}
int temp = prices[0];
int profit = 0;
for(int i=0; i<prices.size();i++)
{
if (prices[i] - temp > 0)
{
profit = profit + prices[i] - temp;
}
temp = prices[i];
}
return profit;
}
};
三、買賣股票的最佳時機 III
給定一個數組,它的第 i 個元素是一支給定的股票在第 i 天的價格。
設計一個演算法來計算你所能獲取的最大利潤。你最多可以完成 兩筆 交易。
注意: 你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。
示例 1:
輸入: [3,3,5,0,0,3,1,4] 輸出: 6 解釋: 在第 4 天(股票價格 = 0)的時候買入,在第 6 天(股票價格 = 3)的時候賣出,這筆交易所能獲得利潤 = 3-0 = 3 。 隨後,在第 7 天(股票價格 = 1)的時候買入,在第 8 天 (股票價格 = 4)的時候賣出,這筆交易所能獲得利潤 = 4-1 = 3 。
示例 2:
輸入: [1,2,3,4,5] 輸出: 4 解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接連購買股票,之後再將它們賣出。 因為這樣屬於同時參與了多筆交易,你必須在再次購買前出售掉之前的股票。
示例 3:
輸入: [7,6,4,3,1] 輸出: 0 解釋: 在這個情況下, 沒有交易完成, 所以最大利潤為 0。
分析:此題加深了難度,限制了建議次數不大於2。最開始的想法是二分,遍歷所有值作為二分點,分成左右兩部分,分別求利潤再求和,最後取最大,時間複雜度O(N^2),結果在倒數第二個評測時超時。優化一下,可以先從前往後遍歷,按照 I 中的思路,將遍歷到的每個值對應的最大利潤存在一個列表中,然後從後往前遍歷,在求此時的最大利潤時,同時加上陣列中的對應值,再取最大,即為所求。
python實現(二分,超時):
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
profit = 0
for i in range(len(prices)):
minprice1 = prices[0]
profit1 = 0
minprice2 = prices[i]
profit2 = 0
for m in range(0,i):
minprice1 = min(prices[m],minprice1)
profit1 = max(profit1,prices[m]-minprice1)
for n in range(i,len(prices)):
minprice2 = min(prices[n],minprice2)
profit2 = max(profit2,prices[n]-minprice2)
profit = max(profit,profit1+profit2)
return profit
python實現:
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if len(prices)<2:
return 0
minprice = prices[0]
maxprice = prices[len(prices)-1]
profit1 = 0
profit2 = 0
profit = 0
a = []
for m in range(0,len(prices)):
profit1 = max(profit1,prices[m]-minprice)
minprice = min(prices[m],minprice)
a.append(profit1)
for n in range(len(prices)-2,-1,-1):
maxprice = max(prices[n],maxprice)
profit2 = max(profit2,maxprice-prices[n])
profit = max(profit,a[n]+profit2)
return profit
C++實現:
class Solution {
public:
int maxProfit(vector<int> &prices) {
if(prices.empty())
return 0;
int minprice = prices[0];
int maxprice = prices[prices.size()-1];
int profit1 = 0;
int profit2 = 0;
int profit = 0;
vector<int> a;
for(int i = 0; i < prices.size(); i++){
profit1 = max(profit1, prices[i] - minprice);
minprice = min(minprice, prices[i]);
a.push_back(profit1);
}
for(int i = prices.size() - 2; i >= 0; i--){
maxprice = max(maxprice, prices[i]);
profit2 = max(profit2, maxprice - prices[i]);
profit = max(profit,profit2 + a[i]);
}
return profit;
}
};