LeetCode #121 is the second most frequently asked problem in coding interviews globally — and it's not even close to being "just an easy problem."
Our analysis of 10,385 verified interview questions across 259 companies shows Best Time to Buy and Sell Stock appeared 199 times across 63 companies — including Amazon, Google, Apple, Bloomberg, Goldman Sachs, and BlackRock.
The catch: most candidates solve it with a brute force O(n²) approach and leave marks on the table. The optimal solution is a single pass, O(n) greedy scan that takes under 10 lines of code. This guide walks you through every approach, every variation, and exactly how to explain it in an interview.
Best Time to Buy and Sell Stock is not just a LeetCode warm-up. It's an interview staple across every tier of company — from FAANG giants to quant hedge funds to unicorn startups.
| Metric | Value |
|---|---|
| Total Interview Appearances | 199 verified mentions |
| Companies That Ask It | 63 companies |
| Global Rank | #2 out of 10,385 questions |
| Difficulty | Easy (follow-ups go to Hard) |
| Core Patterns | Array, Greedy, Dynamic Programming |
Why is this problem so universally popular? Because it tests a fundamental interviewing skill: can you convert a naive O(n²) brute force into a clean O(n) one-pass scan? This "track the minimum so far" technique appears across dozens of harder problems. Mastering it here unlocks a whole family of solutions.
Amazon, Google, Apple, Bloomberg, Goldman Sachs, BlackRock, Adobe, Atlassian, Airbnb, Microsoft, BNY Mellon, Bank of America, American Express, Agoda, Accenture, and 48 more.
LeetCode #121 — Best Time to Buy and Sell Stock
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. If you cannot achieve any profit, return 0.
Input: prices = [7, 1, 5, 3, 6, 4]
Output: 5
Explanation: Buy on day 2 (price=1), sell on day 5 (price=6). Profit = 6 - 1 = 5.
Input: prices = [7, 6, 4, 3, 1]
Output: 0
Explanation: Prices only decrease. No profitable transaction possible.
Input: prices = [2, 4, 1]
Output: 2
Explanation: Buy on day 1 (price=2), sell on day 2 (price=4). Profit = 4 - 2 = 2.
You must buy before you sell. You cannot buy on day 5 and sell on day 2. This makes it fundamentally different from "find max - find min" in any order.
The naive instinct is to check every possible buy-sell pair and track the maximum profit.
def maxProfit(prices):
max_profit = 0
for i in range(len(prices)):
for j in range(i + 1, len(prices)):
profit = prices[j] - prices[i]
max_profit = max(max_profit, profit)
return max_profit
| Metric | Brute Force | Optimal |
|---|---|---|
| Time Complexity | O(n²) | O(n) |
| Space Complexity | O(1) | O(1) |
| Passes Interview? | ❌ Not if you stop here | ✅ Yes |
What to say in the interview: "A brute force approach would be to try every buy-sell pair — O(n²) time. But we don't need to revisit old prices if we track the minimum price seen so far. That gives us O(n) time in a single pass."
The key insight: as you scan left to right, you want to buy at the lowest price seen so far and sell at the highest price after that buy point.
You don't need to look back. At every new price, you ask two questions:
min_price. This is now my best buy point.current_price - min_price greater than my current best profit? If yes — update max_profit.That's it. One pass, two variables.
Tracing prices = [7, 1, 5, 3, 6, 4]:
| Day | Price | min_price | profit today | max_profit |
|---|---|---|---|---|
| 0 | 7 | 7 | 0 | 0 |
| 1 | 1 | 1 (updated) | 0 | 0 |
| 2 | 5 | 1 | 4 | 4 (updated) |
| 3 | 3 | 1 | 2 | 4 |
| 4 | 6 | 1 | 5 | 5 (updated) |
| 5 | 4 | 1 | 3 | 5 |
Final answer: 5. Buy at price 1 (day 1), sell at price 6 (day 4).
def maxProfit(prices: list[int]) -> int:
min_price = float('inf')
max_profit = 0
for price in prices:
if price < min_price:
min_price = price # found a cheaper buy point
elif price - min_price > max_profit:
max_profit = price - min_price # found a better profit
return max_profit
class Solution {
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE;
int maxProfit = 0;
for (int price : prices) {
if (price < minPrice) {
minPrice = price;
} else if (price - minPrice > maxProfit) {
maxProfit = price - minPrice;
}
}
return maxProfit;
}
}
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
let minPrice = Infinity;
let maxProfit = 0;
for (const price of prices) {
if (price < minPrice) {
minPrice = price;
} else if (price - minPrice > maxProfit) {
maxProfit = price - minPrice;
}
}
return maxProfit;
};
min_price and max_profit) regardless of input size. No hash maps, no arrays needed.This is the best achievable complexity for this problem. You must examine every price at least once, so O(n) time is optimal. The O(1) space is a bonus — this solution is strictly better than brute force in time with no space penalty.
Interview-ready explanation: "Time is O(n) because we do a single pass over the array with constant work at each step. Space is O(1) because we only maintain two scalar variables — no auxiliary data structures."
The stock problem is actually a series of 6 LeetCode problems. Interviewers at companies like Goldman Sachs, Google, and Amazon commonly ask follow-ups after you solve #121. Know all of them.
"What if you could buy and sell on multiple days?"
Insight: Capture every upward slope. Add price - prev_price to profit whenever it's positive.
def maxProfit(prices):
profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i - 1]:
profit += prices[i] - prices[i - 1]
return profit
"What if you could complete at most 2 transactions?"
Insight: Track four states — after 1st buy, after 1st sell, after 2nd buy, after 2nd sell. Use DP with these states.
def maxProfit(prices):
buy1 = buy2 = float('-inf')
sell1 = sell2 = 0
for price in prices:
buy1 = max(buy1, -price)
sell1 = max(sell1, buy1 + price)
buy2 = max(buy2, sell1 - price)
sell2 = max(sell2, buy2 + price)
return sell2
"What if you could complete at most k transactions?"
Insight: Generalize the 2-transaction DP to k states. Use a DP table of size k x n. Handle the edge case k >= n//2 (equivalent to unlimited transactions).
"What if after selling, you must wait 1 day before buying again?"
Insight: Track three states — held (stock in hand), sold (just sold today), rest (cooldown or idle). Transition between states each day.
"What if each transaction incurs a fee?"
Insight: Same as unlimited transactions (#122) but subtract fee on each sell. Two states: cash (no stock held), held (holding stock).
"Can you prove the greedy is optimal for unlimited transactions?"
Insight: Any multi-day profit can be decomposed into sum of consecutive daily gains. Capturing every positive day-to-day delta is equivalent to any optimal multi-buy strategy.
| Problem | Constraint | Approach |
|---|---|---|
| LC #121 | 1 transaction | Greedy — track min price |
| LC #122 | Unlimited | Greedy — sum all positives |
| LC #123 | At most 2 | DP — 4 states |
| LC #188 | At most k | DP — k × n table |
| LC #309 | With cooldown | DP — 3 states |
| LC #714 | With fee | DP — 2 states |
The "track minimum/maximum so far" pattern from LC #121 appears across many other problems. Once you internalize it here, you'll recognize it immediately elsewhere.
When a problem asks you to find an optimal pair (i, j) where i < j and some function of arr[i] and arr[j] is maximized — consider tracking the best arr[i] seen so far as you scan right, so each arr[j] can be evaluated in O(1).
With 199 appearances across 63 companies, you will encounter this problem or one of its 6 variants in a real interview. Seeing the code once isn't enough — you need to retrieve it fluently under pressure.
Track all 6 stock variants together on DSAPrep.dev. Tag them under Greedy and Dynamic Programming and the spaced repetition system will surface them at exactly the right intervals — so you don't review too early (wasted effort) or too late (already forgotten).
One problem at a time. One review at a time. Future you will thank present you.