One trade: the best profit
prices[i] is the price of a stock on day i. Choose one day to buy and a later day to sell.
Return the largest profit possible, or 0 if no trade makes money.
Examples
| Input | Output | Why |
|---|---|---|
prices = [7,1,5,3,6,4] | 5 | Buy at 1, sell at 6. |
prices = [7,6,4,3,1] | 0 | Prices only fall: do not trade. |
prices = [2,4,1] | 2 | Buy at 2, sell at 4; the later 1 comes too late. |
Constraints
- 1 ≤ prices.length ≤ 10⁵
- 0 ≤ prices[i] ≤ 10⁴
Hints
Hint 1
Fix the selling day. The best buying day is the cheapest day before it.
Hint 2
Keep the lowest price seen so far while scanning.
Hint 3
Equivalently, this is the maximum subarray of the daily price changes.
Where people lose marks
- Selling before buying (taking the global maximum minus the global minimum).
- Returning a negative profit instead of 0.
Dry run on [7,1,5,3,6,4]
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 6prices701152336445lowest7best0
Day 0: price 7, lowest so far 7; selling today earns 0.
-
Step 2 / 6prices701152336445lowest1best0
Day 1: price 1, lowest so far 1; selling today earns 0.
-
Step 3 / 6prices701152336445lowest1best4
Day 2: price 5, lowest so far 1; selling today earns 4.
-
Step 4 / 6prices701152336445lowest1best4
Day 3: price 3, lowest so far 1; selling today earns 2.
-
Step 5 / 6prices701152336445lowest1best5
Day 4: price 6, lowest so far 1; selling today earns 5.
-
Step 6 / 6prices701152336445lowest1best5
Day 5: price 4, lowest so far 1; selling today earns 3. The best profit is 5.
How to think about it
For each selling day, the best trade buys at the lowest earlier price, so the best profit from selling today is
price − lowest so far. One pass keeping the running minimum and the best profit gives the answer. Seen as DP,
it is the best-ending-here pattern applied to daily changes.
Complexity. Time O(n) · Space O(1)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def max_profit(prices):
lowest, best = prices[0], 0
for p in prices[1:]:
best = max(best, p - lowest) # sell today, bought at the cheapest earlier day
lowest = min(lowest, p)
return best#include <algorithm>
#include <vector>
int solve(const std::vector<int>& prices) {
int lowest = prices[0], best = 0;
for (int p : prices) {
best = std::max(best, p - lowest); // sell today
lowest = std::min(lowest, p);
}
return best;
}class Solution {
public int maxProfit(int[] prices) {
int lowest = prices[0], best = 0;
for (int p : prices) {
best = Math.max(best, p - lowest); // sell today
lowest = Math.min(lowest, p);
}
return best;
}
}function maxProfit(prices) {
let lowest = prices[0], best = 0;
for (const p of prices) {
best = Math.max(best, p - lowest); // sell today
lowest = Math.min(lowest, p);
}
return best;
}fn solve(prices: &[i64]) -> i64 {
let (mut lowest, mut best) = (prices[0], 0);
for &p in prices {
best = best.max(p - lowest); // sell today
lowest = lowest.min(p);
}
best
}solve :: [Int] -> Int
solve prices = maximum (0 : zipWith (-) prices (scanl1 min prices)) -- price minus the lowest so far
Variants to try
- Unlimited trades: add every positive daily change.
- At most two trades, or k trades: DP over (day, trades used, holding or not).
- A cooldown after each sale, or a fee per trade.
Next problems
The largest-sum subarray
Return the largest sum of a non-empty contiguous subarray: the best sum ending at each position, extend or restart.
Open the problem → Medium20 minThe largest product of a subarray
Return the largest product of a non-empty contiguous subarray. A negative number swaps the best and the worst, so keep both.
Open the problem → Medium20 minThe largest sum on a circle
The list wraps around. The best stretch either does not wrap (ordinary Kadane) or does, and then it is the total minus the worst stretch.
Open the problem →Write a solution and run it against the real test table.
Keep going
The largest-sum subarray
Return the largest sum of a non-empty contiguous subarray: the best sum ending at each position, extend or restart.
Open the problem → Medium20 minThe largest product of a subarray
Return the largest product of a non-empty contiguous subarray. A negative number swaps the best and the worst, so keep both.
Open the problem → Medium20 minThe largest sum on a circle
The list wraps around. The best stretch either does not wrap (ordinary Kadane) or does, and then it is the total minus the worst stretch.
Open the problem → Dynamic programmingThe pattern behind it
Write the recursion, notice the repeats, fill a table in an order that makes each entry final.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.