Best Time to Buy and Sell Stock
Problem
prices, where prices[i] is a stock's price on day
i. You may make one trade: buy on some day and sell on a strictly
later day. Return the largest profit you can lock in, or 0 if every
possible trade loses money.prices = [7,1,5,3,6,4]Output5 (buy at 1, sell at 6)prices = [7,6,4,3,1]Output0 (prices only fall)1 ≤ n ≤ 105 · 0 ≤ prices[i] ≤ 104
Try it yourself
class Solution {
public int maxProfit(int[] prices) {
}
}
Instinct "In place", "O(1) extra space" or "one pass" over an array? Think write pointer, reversal, prefix/suffix passes or using indices as storage.
Memory hack Read fast, write slow, reverse to rotate, and let the index be the hash.
Open the Array Manipulation guide →Approaches
Brute ForceTry Every Buy/Sell Pair
O(n2)Space O(1)Fix a buy day i, then try every later sell day j
and keep the best prices[j] - prices[i]. Starting the answer at
0 covers the “don't trade” option.
public int maxProfit(int[] prices) { int best = 0; for (int buy = 0; buy < prices.length; buy++) { for (int sell = buy + 1; sell < prices.length; sell++) { best = Math.max(best, prices[sell] - prices[buy]); } } return best; }
Obviously correct, but ~5·109 pair checks at n = 105 times out.
BetterSuffix Maximum Array
O(n)Space O(n)Precompute maxAfter[i] = highest price on day i or
later (one right-to-left pass). Buying on day i then earns at most
maxAfter[i] - prices[i], so one more pass finds the answer.
public int maxProfit(int[] prices) { int n = prices.length; int[] maxAfter = new int[n]; // max price from day i to the end maxAfter[n - 1] = prices[n - 1]; for (int i = n - 2; i >= 0; i--) { maxAfter[i] = Math.max(prices[i], maxAfter[i + 1]); } int best = 0; for (int i = 0; i < n; i++) { best = Math.max(best, maxAfter[i] - prices[i]); } return best; }
Linear time, but the helper array costs O(n) memory.
OptimalOne Pass — Track the Cheapest Day
O(n)Space O(1)Flip the view: treat each day as the sell day. The best buy for it
is the lowest price before it, which we keep in minPrice. Update the
profit first, then the minimum, so we never sell before we buy.
public int maxProfit(int[] prices) { int minPrice = Integer.MAX_VALUE; // cheapest price seen so far int best = 0; for (int price : prices) { if (price < minPrice) { minPrice = price; // better day to buy } else { best = Math.max(best, price - minPrice); // sell today? } } return best; }
Dry runprices = [7,1,5,3,6,4]
- d=07d m15364min=7, best=0
- d=171d m5364new min=1
- d=271m5d3645-1=4 → best=4
- d=371m53d643-1=2, keep 4
- d=471m536d46-1=5 → best=5
- d=571m5364d4-1=3 → 5 ✔
Single pass, two variables — the expected interview answer.
At a glance
| Level | Approach | Time | Space |
|---|---|---|---|
| Brute Force | Try Every Buy/Sell Pair | O(n2) | O(1) |
| Better | Suffix Maximum Array | O(n) | O(n) |
| Optimal | One Pass — Track the Cheapest Day | O(n) | O(1) |
- Taking
max - minof the whole array — the minimum may come after the maximum. - Returning a negative number when prices only fall — the answer floors at
0. - Pairing a price with a minimum taken from a later day — that sells before buying.
- Say the brute force in one line, then ask: “for a fixed sell day, which buy day wins?”
- Name the invariant:
minPrice= cheapest price strictly before or on today. - Mention the Kadane link — it sets up the multi-transaction follow-ups nicely.
(i < j) where the score depends on one earlier and one later element.