259. Best Time to Buy and Sell Stock
š LeetCode Problem: 121. Best Time to Buy and Sell Stock
š Difficulty: Easy
š·ļø Topics: Array, Dynamic Programming, State Machines
Problem Statement
You are given an array prices where prices[i] is the price of a given stock on the i-th day.
You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.
Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.
Example 1:
Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Example 2:
Input: prices = [7,6,4,3,1]
Output: 0
Explanation: No profit possible, return 0.
Constraints:
- 1 <= prices.length <= 10^5
- 0 <= prices[i] <= 10^4
š§ Understanding The Problem (By Hand)
Let Me Work Example 1 Step By Step
prices = [7, 1, 5, 3, 6, 4]
0 1 2 3 4 5 (indices)
Rule: Buy one day, sell a LATER day
Let me try all possible buy-sell pairs:
Buy day 0 (price=7):
Sell day 1: 1 - 7 = -6 (loss)
Sell day 2: 5 - 7 = -2 (loss)
Sell day 3: 3 - 7 = -4 (loss)
Sell day 4: 6 - 7 = -1 (loss)
Sell day 5: 4 - 7 = -3 (loss)
Buy day 1 (price=1):
Sell day 2: 5 - 1 = 4 ā
Sell day 3: 3 - 1 = 2
Sell day 4: 6 - 1 = 5 āā BEST!
Sell day 5: 4 - 1 = 3
Buy day 2 (price=5):
Sell day 3: 3 - 5 = -2
Sell day 4: 6 - 5 = 1
Sell day 5: 4 - 5 = -1
Buy day 3 (price=3):
Sell day 4: 6 - 3 = 3
Sell day 5: 4 - 3 = 1
Buy day 4 (price=6):
Sell day 5: 4 - 6 = -2
Maximum profit = 5 (buy at 1, sell at 6)
What Did I Learn?
Key insight:
To maximize profit, I want to:
- Buy at the LOWEST price
- Sell at the HIGHEST price AFTER that
It's all about finding:
max(prices[j] - prices[i]) where j > i
š¤ Approach 1: Brute Force
The Idea
Try every possible buy-sell pair:
For each buy day i:
For each sell day j > i:
Calculate profit = prices[j] - prices[i]
Track maximum
Code
class Solution {
public int maxProfit(int[] prices) {
int maxProfit = 0;
for (int buy = 0; buy < prices.length; buy++) {
for (int sell = buy + 1; sell < prices.length; sell++) {
int profit = prices[sell] - prices[buy];
maxProfit = Math.max(maxProfit, profit);
}
}
return maxProfit;
}
}
Complexity
TIME: O(n²) - two nested loops
SPACE: O(1)
For n=100,000: 10 billion operations ā TOO SLOW!
š” The Key Observation
Let Me Think Differently
As I go through each day, I can ask:
"If I SELL today, when should I have bought?"
Answer: At the MINIMUM price seen so far!
Let me trace this:
Day 0: price=7
minPrice so far = 7
If sell today: profit = 7 - 7 = 0
maxProfit = 0
Day 1: price=1
minPrice so far = min(7, 1) = 1
If sell today: profit = 1 - 1 = 0
maxProfit = 0
Day 2: price=5
minPrice so far = 1
If sell today: profit = 5 - 1 = 4
maxProfit = 4
Day 3: price=3
minPrice so far = 1
If sell today: profit = 3 - 1 = 2
maxProfit = 4
Day 4: price=6
minPrice so far = 1
If sell today: profit = 6 - 1 = 5 ā
maxProfit = 5
Day 5: price=4
minPrice so far = 1
If sell today: profit = 4 - 1 = 3
maxProfit = 5
Answer: 5 ā
The Pattern
At each day:
1. Update minimum price seen so far
2. Calculate profit if we sell today
3. Update maximum profit
One pass through the array! O(n) ā
šÆ Approach 2: One Pass Solution
Code
class Solution {
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE;
int maxProfit = 0;
for (int price : prices) {
// Update minimum price
minPrice = Math.min(minPrice, price);
// Calculate profit if we sell today
int profit = price - minPrice;
// Update maximum profit
maxProfit = Math.max(maxProfit, profit);
}
return maxProfit;
}
}
Complete Trace
prices = [7, 1, 5, 3, 6, 4]
i=0, price=7:
minPrice = min(INF, 7) = 7
profit = 7 - 7 = 0
maxProfit = max(0, 0) = 0
i=1, price=1:
minPrice = min(7, 1) = 1
profit = 1 - 1 = 0
maxProfit = max(0, 0) = 0
i=2, price=5:
minPrice = min(1, 5) = 1
profit = 5 - 1 = 4
maxProfit = max(0, 4) = 4
i=3, price=3:
minPrice = min(1, 3) = 1
profit = 3 - 1 = 2
maxProfit = max(4, 2) = 4
i=4, price=6:
minPrice = min(1, 6) = 1
profit = 6 - 1 = 5
maxProfit = max(4, 5) = 5
i=5, price=4:
minPrice = min(1, 4) = 1
profit = 4 - 1 = 3
maxProfit = max(5, 3) = 5
Return 5 ā
Complexity
TIME: O(n) - single pass
SPACE: O(1) - only two variables
Much better! ā
š Key Insights
The Simple Pattern
Problem: Find max(prices[j] - prices[i]) where j > i
Solution: For each day j:
- Track minimum price before day j
- Calculate profit = prices[j] - minimum
- Track maximum profit
This reduces O(n²) to O(n)!
Why This Works
We don't need to try all pairs!
For any sell day j:
Best buy day = day with minimum price before j
By tracking minimum as we go:
We automatically find the best buy day for each sell day
š» Complete Working Code
class Solution {
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE;
int maxProfit = 0;
for (int price : prices) {
minPrice = Math.min(minPrice, price);
maxProfit = Math.max(maxProfit, price - minPrice);
}
return maxProfit;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.maxProfit(new int[] {7,1,5,3,6,4})); // 5
System.out.println(sol.maxProfit(new int[] {7,6,4,3,1})); // 0
}
}
š Quick Revision
Algorithm
minPrice = infinity
maxProfit = 0
For each price:
minPrice = min(minPrice, price)
profit = price - minPrice
maxProfit = max(maxProfit, profit)
Return maxProfit
Quick Implementation
public class Solution {
public int maxProfit(int[] a) {
// return bruteForce(a);
return dp(a);
}
private int dp(int[] a) {
int res = 0;
// consider example [7,1,5,3,6,4]
// step 1: take 7
int minSoFar = a[0];
// step 2: start from 1
for (int i = 1; i < a.length; i++) {
res = Math.max(res, a[i] - minSoFar);
// step 3: track min so far found.
// put it on paper. So easy
minSoFar = Math.min(minSoFar, a[i]);
}
return res;
}
private int bruteForce(int[] a) {
int res = 0;
for (int i = 0; i < a.length; i++) {
// why j = i + 1?
// becuase you can sell only on any day > i only.
// and you cannot sell on the same day when we buy it.
for (int j = i + 1; j < a.length; j++) {
res = Math.max(res, a[j] - a[i]);
}
}
return res;
}
public static void main(String[] args) {
Solution s = new Solution();
System.out.println(s.maxProfit(new int[] { 7, 1, 5, 3, 6, 4 }) == 5);
System.out.println(s.maxProfit(new int[] { 7, 6, 4, 3, 1 }) == 0);
}
}
Complexity
TIME: O(n)
SPACE: O(1)
Key Idea
Track minimum price seen so far
Calculate profit if we sell today
Keep maximum profit
š Done!
Simple problem with simple solution: - ā One pass through array - ā Track minimum price - ā Calculate profit at each step - ā O(n) time, O(1) space
Clean and efficient! ā