Skip to content

Best Time to Buy and Sell Stock II

Given an integer array prices where prices[i] is the price of a given stock on the i-th day, find the maximum profit you can achieve. You may complete as many transactions as you like (buy one and sell one share of the stock multiple times) with the following restrictions:

  • After you sell your stock, you cannot buy stock on the same day (you must cool down for one day).
  • You may not engage in multiple transactions simultaneously (you must sell before you buy again).
InputOutputExplanation
[7, 1, 5, 3, 6, 4]7Buy at 1, sell at 5 (+4); buy at 3, sell at 6 (+3). Total profit = 7.
[1, 2, 3, 4, 5]4Buy at 1, sell at 5 (profit = 4). Or buy/sell at each step: (2-1) + (3-2) + (4-3) + (5-4) = 4.
[7, 6, 4, 3, 1]0Prices only decrease, no profit possible.
  • 1 <= prices.length <= 3 * 10^4
  • 0 <= prices[i] <= 10^4
ApproachTimeSpaceKey InsightBest When
Greedy (Peak Valley)O(n)O(1)Capture every upward movementGeneral case — simplest to implement
Dynamic ProgrammingO(n)O(1)Track holding/non-holding statesInterview deep dive / follow-up practice
  • Pick Greedy if you want the intuitive, elegant solution.
  • Pick Dynamic Programming if you want to understand the general state-machine pattern.
Best For Simplicity
Greedy Peak Valley
O(n) time · O(1) space
Advanced Pattern
Dynamic Programming
O(n) time · O(1) space
Section titled “Approach 1: Greedy Peak Valley (Recommended)”
★ Recommended

Whenever the price goes up from one day to the next, add that difference to the profit. This captures every local upward movement without explicitly identifying peaks and valleys.

Why it works: Any mountain can be broken into a series of small uphill steps. Summing all the steps equals the total climb.

⏱ Time O(n) Single pass 💾 Space O(1) No extra memory

Input: prices = [7, 1, 5, 3, 6, 4]

DayPricePreviousDifferenceActionCumulative Profit
07Start0
1171-7 = -6Price down, skip0
2515-1 = 4Price up, add 40 + 4 = 4
3353-5 = -2Price down, skip4
4636-3 = 3Price up, add 34 + 3 = 7
5464-6 = -2Price down, skip7

Result: max_profit = 7

This is equivalent to: Buy at 1, sell at 5 (profit 4) + Buy at 3, sell at 6 (profit 3) = 7 total.

Animated walkthrough

How the greedy peak-valley solution finds the answer

Watch how every upward price movement is captured and summed to find the total maximum profit.

Step 1 of 5
Waiting to begin...
Array state
Memory / lookup state

function bestTimeToBuyAndSellStockIIGreedy(prices):
maxProfit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
maxProfit += prices[i] - prices[i-1]
return maxProfit
best_time_to_buy_and_sell_stock_ii_greedy.py
from typing import List
def best_time_to_buy_and_sell_stock_ii_greedy(prices: List[int]) -> int:
"""
Greedy approach: capture every upward movement.
Time: O(n), Space: O(1)
"""
max_profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i - 1]:
max_profit += prices[i] - prices[i - 1]
return max_profit
print(best_time_to_buy_and_sell_stock_ii_greedy([7, 1, 5, 3, 6, 4])) # 7
print(best_time_to_buy_and_sell_stock_ii_greedy([1, 2, 3, 4, 5])) # 4
print(best_time_to_buy_and_sell_stock_ii_greedy([7, 6, 4, 3, 1])) # 0
🎯 Interview Favourite

Track two states: holding a stock and not holding a stock. For each day, decide whether to buy, sell, or hold based on which decision maximizes profit.

This approach generalizes to problems with cooldown periods or transaction limits (e.g., problem #309 and #123).

⏱ Time O(n) Single pass 💾 Space O(1) Two variables

Input: prices = [7, 1, 5, 3, 6, 4]

DayPriceholdno_holdInterpretation
Init-70Start with price 7: either bought at -7 or nothing at 0
11max(-7, 0-1) = -1max(0, -7+1) = 0Better to buy today at 1 than before
25max(-1, 0-5) = -1max(0, -1+5) = 4Sell today for profit 4
33max(-1, 4-3) = 1max(4, -1+3) = 4Option to buy again at 3
46max(1, 4-6) = 1max(4, 1+6) = 7Sell at 6 for total profit 7
54max(1, 7-4) = 3max(7, 1+4) = 7Could buy again, but profit stays 7

Result: max_profit = no_hold at the end = 7

function bestTimeToBuyAndSellStockIIDP(prices):
hold = -prices[0]
no_hold = 0
for i in range(1, len(prices)):
hold = max(hold, no_hold - prices[i])
no_hold = max(no_hold, hold + prices[i])
return no_hold
best_time_to_buy_and_sell_stock_ii_dp.py
from typing import List
def best_time_to_buy_and_sell_stock_ii_dp(prices: List[int]) -> int:
"""
Dynamic Programming approach: track holding and not holding states.
Time: O(n), Space: O(1)
"""
if not prices or len(prices) < 2:
return 0
hold = -prices[0] # profit if holding stock after day 0
no_hold = 0 # profit if not holding stock after day 0
for i in range(1, len(prices)):
# Either hold from before or buy today (reset from no_hold)
hold = max(hold, no_hold - prices[i])
# Either don't hold from before or sell today (from hold)
no_hold = max(no_hold, hold + prices[i])
return no_hold
print(best_time_to_buy_and_sell_stock_ii_dp([7, 1, 5, 3, 6, 4])) # 7
print(best_time_to_buy_and_sell_stock_ii_dp([1, 2, 3, 4, 5])) # 4
print(best_time_to_buy_and_sell_stock_ii_dp([7, 6, 4, 3, 1])) # 0
✓ Simple

A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.

⏱ Time O(n) Optimized complexity 💾 Space O(1) Efficient space usage
function approach3():
// Implementation approach goes here
best_time_to_buy_and_sell_stock_ii_space_optimized.py
"""
Solution for Best Time to Buy and Sell Stock II
"""
def solve():
"""Implementation for approach 3 of Best Time to Buy and Sell Stock II"""
pass
if __name__ == "__main__":
print("Solution ready")