Skip to content

Commit 09c95f1

Browse files
committed
refactor(algorithms, dynamic-programming): buy and sell stock 3
1 parent d49ecf8 commit 09c95f1

13 files changed

Lines changed: 124 additions & 66 deletions

algorithms/dynamic_programming/buy_sell_stock/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,58 @@ Output: 0
8686
Explanation: In this case, no transaction is done, i.e. max profit = 0.
8787
```
8888

89+
## Solution
90+
91+
The solution uses a constant space, state-compressed dynamic programming approach to compute the maximum profit
92+
achievable, with at most 2 stock transactions in a single pass through the prices array. The updates are performed each
93+
day greedily, but the underlying logic is dynamic programming: each variable represents the best possible outcome up to
94+
the current point and depends on previously computed states. The core intuition is to model the problem as moving through
95+
four logical states: the cost of the first buy, the profit after the first sell, the effective cost of the second buy
96+
(after reinvesting the first profit), and the profit after the second sell. By continuously updating these values as we
97+
scan prices, we always keep track of the best possible outcome to date. The key insight is that the cost of the second
98+
buy can be reduced by the profit earned from the first transaction, allowing the two transactions to be combined optimally
99+
without overlap. This approach avoids the use of explicit dynamic programming tables and achieves optimal efficiency.
100+
101+
Now, let’s look at the steps of the solution:
102+
103+
1. We initialize four variables: t1Cost and t2Cost to infinity to represent the minimum cost of the first and second
104+
buys, and t1Profit and t2Profit to 0 to represent the maximum profit after the first and second sells.
105+
2. We iterate through each price[i] in the prices array.
106+
- We update t1Cost to be the minimum of its current value and the current price, ensuring we always track the lowest
107+
price to buy the first stock.
108+
- We update t1Profit to be the maximum of its current value and the profit that would result from selling at the
109+
current price after buying at t1Cost.
110+
- Next, we update t2Cost to be the minimum of its current value and (price − t1Profit), which represents the
111+
effective cost of buying the second stock after reinvesting the profit from the first transaction.
112+
- We then update t2Profit to be the maximum of its current value and the profit that would result from selling at the
113+
current price after the second buy.
114+
3. After all prices have been processed, t2Profit contains the maximum profit achievable with at most two non-overlapping
115+
transactions, and we return this value.
116+
117+
![Solution 1](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_1.png)
118+
![Solution 2](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_2.png)
119+
![Solution 3](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_3.png)
120+
![Solution 4](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_4.png)
121+
![Solution 5](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_5.png)
122+
![Solution 6](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_6.png)
123+
![Solution 7](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_7.png)
124+
![Solution 8](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_8.png)
125+
![Solution 9](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_9.png)
126+
![Solution 10](./images/solutions/best_time_to_buy_and_sell_stock_3_solution_10.png)
127+
128+
### Time Complexity
129+
130+
The time complexity of this solution is O(n), where n is the length of the input array prices. This is because the
131+
algorithm makes a single pass through the array and, for each price, performs a constant number of arithmetic operations
132+
and comparisons to update the four tracking variables. As no nested loops or additional passes are involved, the total
133+
running time grows linearly with the number of days.
134+
135+
### Space Complexity
136+
137+
The space complexity of this solution is O(1). The solution uses a fixed number of variables regardless of the input
138+
size. No additional data structures proportional to the input size are required, so the extra space used remains
139+
constant even as the input array grows.
140+
89141
---
90142

91143
# Best Time To Buy and Sell Stock With Transaction Fee

algorithms/dynamic_programming/buy_sell_stock/__init__.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,9 @@ def max_profit_2(prices: List[int]) -> int:
7878

7979

8080
def max_profit_3(prices: List[int]) -> int:
81-
if not prices:
82-
return 0
83-
8481
number_of_prices = len(prices)
8582

86-
if number_of_prices < 2:
83+
if not prices or number_of_prices < 2:
8784
return 0
8885

8986
forward_profit, backward_profit = [0] * number_of_prices, [0] * number_of_prices
@@ -105,6 +102,38 @@ def max_profit_3(prices: List[int]) -> int:
105102
return profit
106103

107104

105+
def max_profit_3_state_compressed_dp(prices: List[int]) -> int:
106+
# t1_cost: minimum price paid for the first buy
107+
# t2_cost: effective minimum price paid for the second buy
108+
# (price reduced by the profit from the first transaction)
109+
t1_cost, t2_cost = float("inf"), float("inf")
110+
111+
# t1_profit: maximum profit achievable after the first sell
112+
# t2_profit: maximum profit achievable after the second sell
113+
t1_profit, t2_profit = 0, 0
114+
115+
# Iterate through each day's stock price
116+
for price in prices:
117+
# Update the minimum cost of the first buy
118+
# We always want to buy at the lowest price seen so far
119+
t1_cost = min(t1_cost, price)
120+
121+
# Update the maximum profit after the first sell
122+
# Selling today gives profit = price - t1_cost
123+
t1_profit = max(t1_profit, price - t1_cost)
124+
125+
# Update the effective cost of the second buy
126+
# The profit from the first transaction reduces the net cost
127+
t2_cost = min(t2_cost, price - t1_profit)
128+
129+
# Update the maximum profit after the second sell
130+
# Selling today after the second buy gives total profit
131+
t2_profit = max(t2_profit, price - t2_cost)
132+
133+
# t2_profit contains the maximum profit with at most two transactions
134+
return t2_profit
135+
136+
108137
def max_profit_with_fee(prices: List[int], fee: int) -> int:
109138
# initially, there is no cash
110139
initial_cash = -math.inf
16.5 KB
Loading
23.3 KB
Loading
35.2 KB
Loading
26.6 KB
Loading
36.5 KB
Loading
35 KB
Loading
36.5 KB
Loading
36.7 KB
Loading

0 commit comments

Comments
 (0)