Best Time to Buy and Sell Stock
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 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:
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. Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.
Visual Representation
Approach: Sliding Window (Two Pointers)
To maximize our profit, we want to buy at the absolutely lowest price possible, and sell at the absolutely highest price after that buy date.
We can solve this efficiently in one pass using a Sliding Window (which in this case is effectively managed by Two Pointers).
- Initialize a
leftpointer (buy day) at index0. - Initialize a
rightpointer (sell day) at index1. - Keep track of a
maxProfitvariable initialized to0. - While the
rightpointer hasn’t reached the end of the array:- Profitable Transaction: If
prices[left] < prices[right], it means buying atleftand selling atrightis profitable!- Calculate the current profit:
prices[right] - prices[left]. - Update
maxProfitif this current profit is greater than our previousmaxProfit.
- Calculate the current profit:
- Found a new low: If
prices[left] >= prices[right], it means our current sell day is actually cheaper than our buy day! This is a fantastic opportunity. Because we want to buy at the lowest possible price, we should immediately slide ourleftpointer to point to this new lowest price atright. - Regardless of the condition, increment the
rightpointer by 1 to check the next day.
- Profitable Transaction: If
- Return the
maxProfit.
NOTE: Why jump
leftall the way torightwhen a lower price is found?
Because any day betweenleftandrighthad a price higher thanprices[left]. Therefore,prices[right]is strictly the lowest price we have seen so far, making it the mathematically optimal new buying point.
Solution
/**
* @param {number[]} prices
* @return {number}
*/
function maxProfit(prices) {
let left = 0; // Buy
let right = 1; // Sell
let maxProfit = 0;
while (right < prices.length) {
// If it's a profitable transaction
if (prices[left] < prices[right]) {
const profit = prices[right] - prices[left];
maxProfit = Math.max(maxProfit, profit);
} else {
// We found a new, even lower price! Slide the buy pointer to this day.
left = right;
}
// Always move the right pointer to the next day
right++;
}
return maxProfit;
}
Complexity Analysis
- Time Complexity: where is the number of days (the length of the
pricesarray). We only iterate through the array once using therightpointer. - Space Complexity: since we are only using a few variables (
left,right,maxProfit) and no dynamically sized data structures.