123. Best Time to Buy and Sell Stock III
Hard
374492Add to ListShare
You are given an array prices
where prices[i]
is the price of a given stock on the ith
day.
Find the maximum profit you can achieve. You may complete at most two transactions.
Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
Example 1:
Input: prices = [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
Example 2:
Input: prices = [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are engaging multiple transactions at the same time. You must sell before buying again.
Example 3:
Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
Example 4:
Input: prices = [1]
Output: 0
Constraints:
1 <= prices.length <= 105
0 <= prices[i] <= 105
超时代码- -||,保存一下
class Solution:
def maxProfit(self, prices: List[int]) -> int:
"""
assert Solution().maxProfit([8, 6, 4, 3, 3, 2, 3, 5, 8, 3, 8, 2, 6]) == 11
assert Solution().maxProfit([2, 1, 4, 5, 2, 9, 7]) == 11
assert Solution().maxProfit([1, 2, 3, 4, 5]) == 4
assert Solution().maxProfit([8, 3, 6, 2, 8, 8, 8, 4, 2, 0, 7, 2, 9, 4, 9]) == 15
assert Solution().maxProfit([2, 1, 2, 0, 1]) == 2
assert Solution().maxProfit([2, 11, 10, 20, 15, 30]) == 33
assert Solution().maxProfit([7, 1, 5, 2, 6, 0, 20, 1, 10]) == 29
assert Solution().maxProfit([7, 1, 5, 2, 6]) == 8
assert Solution().maxProfit([3, 3, 5, 0, 0, 3, 1, 4]) == 6
assert Solution().maxProfit([7, 6, 4, 3, 1]) == 0
解题思路:
dp[n][2]保存前i个数为止取一个区间或2个区间的最优解
start_index_list 保存所有递增序列开头下标
min_index 代表最小数的下标
1. 取一段区间
dp[i][0] = max(dp[i-1][0], prices[i] - min_price),其中 0<i<n, min_price 为前i个出现的最小的数
2. 取两段区间,枚举所有递增序列开头位置i,i左边的一段区间dp[i-1][0]最优解 + i到当前位置的区间
dp[i][1] = max(dp[i][1] , dp[start_index-1][0] + prices[i] - prices[start_index]),
其中 0 <= start_index < i < n, start_index 代表一个递增序列开头下标
时间复杂度:最坏一直驼峰 O(n^2),空间复杂度:O(n)
"""
n = len(prices)
if prices is None or n <= 1:
return 0
dp = [[0 for col in range(2)] for row in range(n)]
start_index_list = list()
min_index = 0
for i in range(1, n):
# 1
dp[i][0] = max(dp[i - 1][0], prices[i] - prices[min_index])
if (i + 1 < n) and (prices[i + 1] >= prices[i] < prices[i - 1]):
# 当前位置为递增起始位置,比左右小
start_index_list.append(i)
# 2
dp[i][1] = dp[i - 1][1]
if (i == n - 1) or (prices[i + 1] < prices[i]):
# 优化:最后一个数或下一个数比当前的小才更新
for j in range(len(start_index_list) - 1, -1, -1):
start_index = start_index_list[j]
if start_index < min_index:
# 做个剪枝,小于最小值前面的都不用遍历了
break
dp[i][1] = max(dp[i][1], dp[start_index - 1][0] + prices[i] - prices[start_index])
if prices[i] < prices[min_index]:
min_index = i
return max(dp[n - 1][0], dp[n - 1][1])
AC
class Solution:
def maxProfit(self, prices: List[int]) -> int:
"""
assert Solution().maxProfit([8, 3, 6, 2, 8, 8, 8, 4, 2, 0, 7, 2, 9, 4, 9]) == 15
assert Solution().maxProfit([8, 6, 4, 3, 3, 2, 3, 5, 8, 3, 8, 2, 6]) == 11
assert Solution().maxProfit([2, 1, 4, 5, 2, 9, 7]) == 11
assert Solution().maxProfit([1, 2, 3, 4, 5]) == 4
assert Solution().maxProfit([2, 1, 2, 0, 1]) == 2
assert Solution().maxProfit([2, 11, 10, 20, 15, 30]) == 33
assert Solution().maxProfit([7, 1, 5, 2, 6, 0, 20, 1, 10]) == 29
assert Solution().maxProfit([7, 1, 5, 2, 6]) == 8
assert Solution().maxProfit([3, 3, 5, 0, 0, 3, 1, 4]) == 6
assert Solution().maxProfit([7, 6, 4, 3, 1]) == 0
解题思路:由121. Best Time to Buy and Sell Stock I 知,对于一段区间,
用f[i]表示0~i为止最大值,只需要遍历一次。此题同理,但是允许最多2段区间。
所以,设g[i]表示i~n为止最大值,结果为max{f(i)+g(i)}
时间复杂度;O(n),空间复杂度:O(n)
"""
if prices is None:
return 0
n = len(prices)
if n <= 1:
return 0
f = [0] * n
min_price = prices[0]
for i in range(1, n):
f[i] = max(f[i - 1], prices[i] - min_price)
min_price = min(min_price, prices[i])
g = [0] * n
max_price = prices[n - 1]
for i in range(n - 2, 0, -1):
g[i] = max(g[i + 1], max_price - prices[i])
max_price = max(max_price, prices[i])
res = 0
for i in range(n):
res = max(res, f[i] + g[i])
return res