You are given an array of integers prices
representing the price of a stock on each day. You are allowed to complete at most three transactions (i.e., buy one and sell one share of the stock multiple times). Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
Find the maximum profit you can achieve.
Example 1:
Input: prices = [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
Example 2:
Input: prices = [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are engaging multiple transactions at the same time. You must sell before buying again.
Example 3:
Input: prices = [7,6,4,3,1]
Output: 0
Explanation: There is no way to make a positive profit, so we do not engage in any transactions.
Constraints:
1 <= prices.length <= 105
0 <= prices[i] <= 105
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding a third transaction involves checking all possible combinations of three transactions within the given dataset. We accomplish this by exhaustively comparing every possible triplet to find the one that meets the specified criteria.
Here's how the algorithm would work step-by-step:
def find_third_transaction_brute_force(transactions):
valid_combinations = []
number_of_transactions = len(transactions)
for first_transaction_index in range(number_of_transactions):
first_transaction = transactions[first_transaction_index]
for second_transaction_index in range(number_of_transactions):
if second_transaction_index == first_transaction_index:
continue
second_transaction = transactions[second_transaction_index]
# We're looking for the third transaction here
for third_transaction_index in range(number_of_transactions):
if third_transaction_index == first_transaction_index or \
third_transaction_index == second_transaction_index:
continue
third_transaction = transactions[third_transaction_index]
# Checking if condition is met.
# Example condition based on indices:
if first_transaction_index < second_transaction_index < third_transaction_index:
valid_combinations.append((first_transaction, second_transaction, third_transaction))
# This is for selecting the third one.
if len(valid_combinations) > 0:
return valid_combinations[0]
# Returns None if no combination exists.
return None
To efficiently find the third transaction, we maintain the best two transactions seen so far. Then, we iterate through the remaining transactions and identify the first one that exceeds the value of our second-best transaction, designating it as the third.
Here's how the algorithm would work step-by-step:
def find_third_transaction(transactions):
first_transaction = None
second_transaction = None
third_transaction = None
for transaction in transactions:
if first_transaction is None:
# Initialize all three to the first transaction.
first_transaction = transaction
second_transaction = transaction
third_transaction = transaction
elif second_transaction is None:
# Initialize second to the current transaction.
second_transaction = transaction
elif third_transaction is None:
# Now we have our first, second and third
third_transaction = transaction
else:
# Replace the oldest transaction with the current.
first_transaction = second_transaction
second_transaction = third_transaction
third_transaction = transaction
return first_transaction
Case | How to Handle |
---|---|
Null or empty prices array | Return 0 immediately, as no transactions are possible. |
Prices array with length less than 2 | Return 0, as at least two prices are needed for a transaction. |
Prices array is sorted in descending order (always losing money) | The algorithm should correctly identify and return 0 profit. |
Prices array contains all identical values | Return 0, as no profit can be made from identical prices. |
Prices array contains very large numbers (potential integer overflow) | Use a data type that can hold larger values, such as long, to prevent overflow during profit calculations. |
Prices array where three transactions are impossible or suboptimal (e.g., most profits can be made with one or two) | The algorithm should correctly determine the maximum profit achievable with at most three transactions, even if fewer transactions yield higher profits. |
Large prices array (performance considerations) | Ensure the solution's time complexity is efficient (e.g., O(n) or O(n log n)) to handle large arrays without excessive runtime. |
Prices array containing negative values (invalid stock prices) | The algorithm should ideally throw an exception or handle the negative prices gracefully as invalid input because stock prices are always non-negative, or it must handle it by taking the absolute value of the number. |