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.
Link to problem

Example 1

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.

Example 2

Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transactions are done and the max profit = 0.

Solutions

Approach 1: Simpleton

The twist in this problem is that it is in series, so we cannot just take min and max and call it a day.

This approach is rather simple, hence the name, and also the first approach that I thought of.

Basically, we iterate over the array while keeping track of our profits and minimum.

Pseudocode

minimum = prices[0]
profit = 0

loop over prices skipping first element
    if currentPrice < minimum
        minimum = currentPrice
    
    if currentPrice - minimum > profit
        profit = currentPrice - minimum

return profit

Implementation in Rust

fn max_profit(prices: Vec<i32>) -> i32 {
    let mut profit: i32 = 0;
    let mut minimum: i32 = prices[0];

    for current_price in prices.iter().skip(1) {
        if current_price < &minimum {
            minimum = *current_price 
        }

        if current_price - minimum > profit {
            profit = current_price - minimum;
        }
    }
    profit
}

Time Complexity: $O(n)$
Runtime on LeetCode: $12$ms


Approach 2: Two Pointers

It uses two pointers, one for buying and another for selling.
Similar to the above approach, we iterate over the entire array but use pointers to keep track of buying/selling.

I found this from neetcode but it’s pretty much the same as my approach, surprisingly it is also slightly slower than the simpleton approach. Guess simple truly is better than complex, right Guido?

Pseudocode

left_ptr = 0  (buy ptr)
right_ptr = 1 (sell ptr)
max_profit = 0

loop over prices until right_ptr is at the end
    if price[left_ptr] < price[right_ptr]
        profit = price[right_ptr] - price[left_ptr]
        if profit > max_profit
            max_profit = profit
    else
        left_ptr = right_ptr
    right_ptr += 1

return max_profit

Implementation in Rust

fn max_profit(prices: Vec<i32>) -> i32 {
    let mut max_profit: i32 = 0;
    let mut left_ptr = 0;
    let mut right_ptr = 1;

    while right_ptr < prices.len() - 1 {
        if prices[left_ptr] < prices[right_ptr] {
            let profit = prices[right_ptr] - prices[left_ptr];

            if profit > max_profit {
                max_profit = profit;
            }
        } else {
            left_ptr = right_ptr;
        }
        right_ptr += 1
    }
    max_profit
}

Time Complexity: $O(n)$
Runtime on leetcode: $25$ms