-
Notifications
You must be signed in to change notification settings - Fork 17
/
best-time-to-buy-and-sell-stock-iv.py
89 lines (66 loc) · 2.95 KB
/
best-time-to-buy-and-sell-stock-iv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from typing import List
from functools import lru_cache
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
profits = []
min_cur, max_cur = prices[0] if prices else 0, prices[0] if prices else 0
for price in range(1, len(prices)):
if prices[price - 1] < prices[price]:
max_cur = prices[price]
else:
profits.append(max_cur - min_cur)
max_cur, min_cur = prices[price], prices[price]
profits.append(max_cur - min_cur)
profits.sort()
return sum(profits[-k:])
def maxProfit(self, k: int, prices: List[int]) -> int:
def profit_unlimited_transactions() -> int:
profit = 0
min_cur, max_cur = prices[0] if prices else 0, prices[0] if prices else 0
for price in range(1, len(prices)):
if prices[price - 1] < prices[price]:
max_cur = prices[price]
else:
profit += max_cur - min_cur
max_cur, min_cur = prices[price], prices[price]
return profit + max_cur - min_cur
def profit_limited_transactions() -> int:
max_transactions = min((len(prices) + 1) // 2 + 1, k + 1)
dp = [[0, 0] for _ in range(max_transactions)]
max_profit = 0
for price in reversed(range(len(prices))):
max_transactions_cur = min((price + 1) // 2 + 1, k + 1)
old_dp = dp
dp = []
for transactions in range(max_transactions_cur):
dp.append([0, 0])
for can_buy in [False, True]:
dp[transactions][can_buy] = max(
old_dp[transactions][can_buy],
old_dp[transactions + 1][False] - prices[price]
if can_buy and transactions < len(old_dp) - 1
else 0,
old_dp[transactions][True] + prices[price]
if not can_buy
else 0,
)
max_profit = max(max_profit, dp[0][True])
return max_profit
if k > len(prices) // 2:
return profit_unlimited_transactions()
return profit_limited_transactions()
def maxProfitTopDown(self, k: int, prices: List[int]) -> int:
@lru_cache(None)
def dp(price: int, transactions: int, can_buy: bool) -> int:
if price == len(prices):
return 0
if transactions > k:
return 0
return max(
dp(price + 1, transactions, can_buy),
dp(price + 1, transactions + 1, False) - prices[price]
if can_buy
else 0,
dp(price + 1, transactions, True) + prices[price] if not can_buy else 0,
)
return dp(0, 0, True)