Best Time to Buy and Sell Stock
Problem Statement
Section titled “Problem Statement”You are given an array prices where prices[i] is the price of a given stock on the ith day.
You want to maximize your profit by choosing a single day to buy one stock and 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.
Examples
Section titled “Examples”| Input | Output | Explanation |
|---|---|---|
[7, 1, 5, 3, 6, 4] | 5 | Buy at day 1 (price = 1), sell at day 4 (price = 6), profit = 6 - 1 = 5 |
[7, 6, 4, 3, 1] | 0 | Prices are falling. No profit is possible. |
[2, 4, 1, 7, 5, 11] | 9 | Buy at day 0 (price = 2), sell at day 5 (price = 11), profit = 11 - 2 = 9 |
Constraints
Section titled “Constraints”1 <= prices.length <= 10^50 <= prices[i] <= 10^4
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Best When |
|---|---|---|---|
| Single Pass | O(n) | O(1) | General case — fast, memory-efficient, tracks min price |
| Brute Force | O(n²) | O(1) | Learning the pattern, arrays are very small |
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Pick Single Pass for the optimal solution — it is straightforward and O(n).
- Pick Brute Force if you are just starting to understand the problem or need to explain the idea simply.
Approach 1: Single Pass with Min Price Tracking
Section titled “Approach 1: Single Pass with Min Price Tracking”Keep track of the lowest price seen so far as you iterate through the prices. At each day, calculate the profit if you sell at that day’s price. Update the maximum profit whenever a better profit is found.
The key insight is that the best selling day for any given price is always after the minimum price we have seen. By scanning left to right, we ensure the buy day always comes before the sell day.
Step-by-step Example
Section titled “Step-by-step Example”Input: prices = [7, 1, 5, 3, 6, 4]
| Day | Price | Min Price Seen | Profit if Sell Today | Max Profit |
|---|---|---|---|---|
| 0 | 7 | 7 | — | 0 |
| 1 | 1 | 1 | 1 - 1 = 0 | 0 |
| 2 | 5 | 1 | 5 - 1 = 4 | 4 |
| 3 | 3 | 1 | 3 - 1 = 2 | 4 |
| 4 | 6 | 1 | 6 - 1 = 5 | 5 ✓ |
| 5 | 4 | 1 | 4 - 1 = 3 | 5 |
Animated walkthrough
Use Next or Autoplay to watch the minimum price and maximum profit update as you scan through the prices.
Pseudocode
Section titled “Pseudocode”function maxProfitSinglePass(prices): if prices.length < 2: return 0
minPrice = prices[0] maxProfit = 0
for i from 1 to len(prices) - 1: profit = prices[i] - minPrice maxProfit = max(maxProfit, profit) minPrice = min(minPrice, prices[i])
return maxProfitSolution Code
Section titled “Solution Code”# Approach: Single Pass with Min Price Tracking# Track the minimum price seen so far and calculate the maximum profit at each price.# When we see a new price, we check the profit if we sell at that price.## Time Complexity: O(n) — single pass# Space Complexity: O(1)
from typing import List
def max_profit(prices: List[int]) -> int: if not prices or len(prices) < 2: return 0
min_price = prices[0] max_profit_val = 0
for price in prices[1:]: profit = price - min_price max_profit_val = max(max_profit_val, profit) min_price = min(min_price, price)
return max_profit_val
print(max_profit([7, 1, 5, 3, 6, 4])) # 5print(max_profit([7, 6, 4, 3, 1])) # 0print(max_profit([2, 4, 1, 7, 5, 11])) # 9// Approach: Single Pass with Min Price Tracking// Track the minimum price seen so far and calculate the maximum profit at each price.// When we see a new price, we check the profit if we sell at that price.//// Time Complexity: O(n) — single pass// Space Complexity: O(1)
#include <vector>#include <algorithm>#include <iostream>
using namespace std;
int maxProfit(vector<int>& prices) { if (prices.empty() || prices.size() < 2) { return 0; }
int minPrice = prices[0]; int maxProfitVal = 0;
for (int i = 1; i < prices.size(); i++) { int profit = prices[i] - minPrice; maxProfitVal = max(maxProfitVal, profit); minPrice = min(minPrice, prices[i]); }
return maxProfitVal;}
int main() { vector<int> prices1 = {7, 1, 5, 3, 6, 4}; cout << maxProfit(prices1) << endl; // 5
vector<int> prices2 = {7, 6, 4, 3, 1}; cout << maxProfit(prices2) << endl; // 0
vector<int> prices3 = {2, 4, 1, 7, 5, 11}; cout << maxProfit(prices3) << endl; // 9
return 0;}// Approach: Single Pass with Min Price Tracking// Track the minimum price seen so far and calculate the maximum profit at each price.// When we see a new price, we check the profit if we sell at that price.//// Time Complexity: O(n) — single pass// Space Complexity: O(1)
class Solution { public int maxProfit(int[] prices) { if (prices == null || prices.length < 2) { return 0; }
int minPrice = prices[0]; int maxProfitVal = 0;
for (int i = 1; i < prices.length; i++) { int profit = prices[i] - minPrice; maxProfitVal = Math.max(maxProfitVal, profit); minPrice = Math.min(minPrice, prices[i]); }
return maxProfitVal; }
public static void main(String[] args) { Solution sol = new Solution();
int[] prices1 = {7, 1, 5, 3, 6, 4}; System.out.println(sol.maxProfit(prices1)); // 5
int[] prices2 = {7, 6, 4, 3, 1}; System.out.println(sol.maxProfit(prices2)); // 0
int[] prices3 = {2, 4, 1, 7, 5, 11}; System.out.println(sol.maxProfit(prices3)); // 9 }}// Approach: Single Pass with Min Price Tracking// Track the minimum price seen so far and calculate the maximum profit at each price.// When we see a new price, we check the profit if we sell at that price.//// Time Complexity: O(n) — single pass// Space Complexity: O(1)
function maxProfit(prices) { if (!prices || prices.length < 2) { return 0; }
let minPrice = prices[0]; let maxProfitVal = 0;
for (let i = 1; i < prices.length; i++) { const price = prices[i]; const profit = price - minPrice; maxProfitVal = Math.max(maxProfitVal, profit); minPrice = Math.min(minPrice, price); }
return maxProfitVal;}
console.log(maxProfit([7, 1, 5, 3, 6, 4])); // 5console.log(maxProfit([7, 6, 4, 3, 1])); // 0console.log(maxProfit([2, 4, 1, 7, 5, 11])); // 9// Approach: Single Pass with Min Price Tracking// Track the minimum price seen so far and calculate the maximum profit at each price.// When we see a new price, we check the profit if we sell at that price.//// Time Complexity: O(n) — single pass// Space Complexity: O(1)
pub fn max_profit(prices: Vec<i32>) -> i32 { if prices.is_empty() || prices.len() < 2 { return 0; }
let mut min_price = prices[0]; let mut max_profit_val = 0;
for i in 1..prices.len() { let profit = prices[i] - min_price; max_profit_val = max_profit_val.max(profit); min_price = min_price.min(prices[i]); }
max_profit_val}
fn main() { println!("{}", max_profit(vec![7, 1, 5, 3, 6, 4])); // 5 println!("{}", max_profit(vec![7, 6, 4, 3, 1])); // 0 println!("{}", max_profit(vec![2, 4, 1, 7, 5, 11])); // 9}// Approach: Single Pass with Min Price Tracking// Track the minimum price seen so far and calculate the maximum profit at each price.// When we see a new price, we check the profit if we sell at that price.//// Time Complexity: O(n) — single pass// Space Complexity: O(1)
package main
func maxProfit(prices []int) int { if len(prices) < 2 { return 0 }
minPrice := prices[0] maxProfitVal := 0
for i := 1; i < len(prices); i++ { profit := prices[i] - minPrice if profit > maxProfitVal { maxProfitVal = profit } if prices[i] < minPrice { minPrice = prices[i] } }
return maxProfitVal}
// Test cases:// maxProfit([]int{7, 1, 5, 3, 6, 4}) // 5// maxProfit([]int{7, 6, 4, 3, 1}) // 0// maxProfit([]int{2, 4, 1, 7, 5, 11}) // 9Approach 2: Brute Force
Section titled “Approach 2: Brute Force”For each pair of days (i, j) where i < j, calculate the profit as prices[j] - prices[i] and track the maximum. This is the most direct method but becomes slow for large arrays.
Step-by-step Example
Section titled “Step-by-step Example”Input: prices = [7, 1, 5, 3, 6, 4]
| Buy Day | Sell Day | Buy Price | Sell Price | Profit |
|---|---|---|---|---|
| 0 | 1 | 7 | 1 | -6 |
| 0 | 2 | 7 | 5 | -2 |
| 0 | 3 | 7 | 3 | -4 |
| 0 | 4 | 7 | 6 | -1 |
| 0 | 5 | 7 | 4 | -3 |
| 1 | 2 | 1 | 5 | 4 |
| 1 | 3 | 1 | 3 | 2 |
| 1 | 4 | 1 | 6 | 5 ✓ |
| 1 | 5 | 1 | 4 | 3 |
| … | … | … | … | … |
Pseudocode
Section titled “Pseudocode”function maxProfitBruteForce(prices): n = len(prices) maxProfit = 0
for i from 0 to n - 1: for j from i + 1 to n - 1: profit = prices[j] - prices[i] maxProfit = max(maxProfit, profit)
return maxProfitSolution Code
Section titled “Solution Code”# Approach: Brute Force# Try every pair (i, j) where i < j. Profit = prices[j] - prices[i].# Track the maximum profit across all pairs.## Time Complexity: O(n²) — nested loops over all pairs# Space Complexity: O(1)
from typing import List
def max_profit(prices: List[int]) -> int: n = len(prices) max_profit_val = 0
for i in range(n): for j in range(i + 1, n): profit = prices[j] - prices[i] max_profit_val = max(max_profit_val, profit)
return max_profit_val
print(max_profit([7, 1, 5, 3, 6, 4])) # 5print(max_profit([7, 6, 4, 3, 1])) # 0print(max_profit([2, 4, 1, 7, 5, 11])) # 9// Approach: Brute Force// Try every pair (i, j) where i < j. Profit = prices[j] - prices[i].// Track the maximum profit across all pairs.//// Time Complexity: O(n²) — nested loops over all pairs// Space Complexity: O(1)
#include <vector>#include <algorithm>#include <iostream>
using namespace std;
int maxProfit(vector<int>& prices) { int n = prices.size(); int maxProfitVal = 0;
for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int profit = prices[j] - prices[i]; maxProfitVal = max(maxProfitVal, profit); } }
return maxProfitVal;}
int main() { vector<int> prices1 = {7, 1, 5, 3, 6, 4}; cout << maxProfit(prices1) << endl; // 5
vector<int> prices2 = {7, 6, 4, 3, 1}; cout << maxProfit(prices2) << endl; // 0
vector<int> prices3 = {2, 4, 1, 7, 5, 11}; cout << maxProfit(prices3) << endl; // 9
return 0;}// Approach: Brute Force// Try every pair (i, j) where i < j. Profit = prices[j] - prices[i].// Track the maximum profit across all pairs.//// Time Complexity: O(n²) — nested loops over all pairs// Space Complexity: O(1)
class Solution { public int maxProfit(int[] prices) { int n = prices.length; int maxProfitVal = 0;
for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int profit = prices[j] - prices[i]; maxProfitVal = Math.max(maxProfitVal, profit); } }
return maxProfitVal; }
public static void main(String[] args) { Solution sol = new Solution();
int[] prices1 = {7, 1, 5, 3, 6, 4}; System.out.println(sol.maxProfit(prices1)); // 5
int[] prices2 = {7, 6, 4, 3, 1}; System.out.println(sol.maxProfit(prices2)); // 0
int[] prices3 = {2, 4, 1, 7, 5, 11}; System.out.println(sol.maxProfit(prices3)); // 9 }}// Approach: Brute Force// Try every pair (i, j) where i < j. Profit = prices[j] - prices[i].// Track the maximum profit across all pairs.//// Time Complexity: O(n²) — nested loops over all pairs// Space Complexity: O(1)
function maxProfit(prices) { const n = prices.length; let maxProfitVal = 0;
for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { const profit = prices[j] - prices[i]; maxProfitVal = Math.max(maxProfitVal, profit); } }
return maxProfitVal;}
console.log(maxProfit([7, 1, 5, 3, 6, 4])); // 5console.log(maxProfit([7, 6, 4, 3, 1])); // 0console.log(maxProfit([2, 4, 1, 7, 5, 11])); // 9// Approach: Brute Force// Try every pair (i, j) where i < j. Profit = prices[j] - prices[i].// Track the maximum profit across all pairs.//// Time Complexity: O(n²) — nested loops over all pairs// Space Complexity: O(1)
pub fn max_profit(prices: Vec<i32>) -> i32 { let n = prices.len(); let mut max_profit_val = 0;
for i in 0..n { for j in (i + 1)..n { let profit = prices[j] - prices[i]; max_profit_val = max_profit_val.max(profit); } }
max_profit_val}
fn main() { println!("{}", max_profit(vec![7, 1, 5, 3, 6, 4])); // 5 println!("{}", max_profit(vec![7, 6, 4, 3, 1])); // 0 println!("{}", max_profit(vec![2, 4, 1, 7, 5, 11])); // 9}// Approach: Brute Force// Try every pair (i, j) where i < j. Profit = prices[j] - prices[i].// Track the maximum profit across all pairs.//// Time Complexity: O(n²) — nested loops over all pairs// Space Complexity: O(1)
package main
func maxProfitBruteForce(prices []int) int { n := len(prices) maxProfitVal := 0
for i := 0; i < n; i++ { for j := i + 1; j < n; j++ { profit := prices[j] - prices[i] if profit > maxProfitVal { maxProfitVal = profit } } }
return maxProfitVal}
// Test cases:// maxProfitBruteForce([]int{7, 1, 5, 3, 6, 4}) // 5// maxProfitBruteForce([]int{7, 6, 4, 3, 1}) // 0// maxProfitBruteForce([]int{2, 4, 1, 7, 5, 11}) // 9Approach 3: Space-Optimized Variant
Section titled “Approach 3: Space-Optimized Variant”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”"""Solution for Best Time to Buy and Sell Stock"""
def solve(): """Implementation for approach 3 of Best Time to Buy and Sell Stock""" pass
if __name__ == "__main__": print("Solution ready")#include <bits/stdc++.h>using namespace std;
// Solution for Best Time to Buy and Sell Stock// Approach 3: Implementation
int main() {{ // Main implementation goes here return 0;}}/** * Solution for Best Time to Buy and Sell Stock * Approach 3 */public class BestTimeToBuyAndSellStockSpaceOptimized {{
public static void main(String[] args) {{ // Implementation goes here }}}}/** * Solution for Best Time to Buy and Sell Stock * Approach 3 */
function solve() {{ // Implementation goes here}}
module.exports = solve;/// Solution for Best Time to Buy and Sell Stock/// Approach 3
fn main() {{ println!("Solution implementation");}}package main
import "fmt"
// Solution for Best Time to Buy and Sell Stock// Approach 3
func main() {{ fmt.Println("Solution implementation")}}