Максимальная прибыль от акций
Условие
Дан массив цен на акции по дням. Найдите максимальную прибыль, если можно совершить только одну покупку и одну продажу.
Покупать нужно до продажи.
Пример
max_profit([7, 1, 5, 3, 6, 4]) → 5 Объяснение: купить в день 2 (цена 1), продать в день 5 (цена 6)
max_profit([7, 6, 4, 3, 1]) → 0 Объяснение: цена только падает, нет прибыли
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Максимальная прибыль от акций
Это классическая задача на алгоритмический анализ потоков данных. Нужно найти пару (день покупки, день продажи) такую, что цена падает и прибыль максимальна. Ключевое ограничение: продажа только после покупки.
Подход: Один проход с отслеживанием минимума
В один проход через массив отслеживаем:
- Минимальная цена видена до текущего дня
- Максимальная прибыль если продать сегодня
def max_profit(prices):
if not prices or len(prices) < 2:
return 0
min_price = prices[0]
max_profit = 0
for price in prices[1:]:
potential_profit = price - min_price
max_profit = max(max_profit, potential_profit)
min_price = min(min_price, price)
return max_profit
print(max_profit([7, 1, 5, 3, 6, 4])) # 5
print(max_profit([7, 6, 4, 3, 1])) # 0
Пошаговое выполнение
Массив: [7, 1, 5, 3, 6, 4]
Шаг 1: price=7 (начало)
min_price = 7, max_profit = 0
Шаг 2: price=1
profit = 1 - 7 = -6
max_profit = max(0, -6) = 0
min_price = min(7, 1) = 1
Шаг 3: price=5
profit = 5 - 1 = 4
max_profit = max(0, 4) = 4
min_price = 1
Шаг 4: price=3
profit = 3 - 1 = 2
max_profit = 4
min_price = 1
Шаг 5: price=6
profit = 6 - 1 = 5 ← Максимум!
max_profit = 5
min_price = 1
Шаг 6: price=4
profit = 4 - 1 = 3
max_profit = 5
С отслеживанием дней
def max_profit_with_days(prices):
if not prices or len(prices) < 2:
return 0, -1, -1
min_price = prices[0]
min_day = 0
max_profit = 0
buy_day = 0
sell_day = 0
for day, price in enumerate(prices[1:], 1):
profit = price - min_price
if profit > max_profit:
max_profit = profit
buy_day = min_day
sell_day = day
if price < min_price:
min_price = price
min_day = day
return max_profit, buy_day, sell_day
Наивный подход (неоптимально)
def max_profit_brute_force(prices):
# O(n^2) - проверяем все пары
max_profit = 0
for i in range(len(prices)):
for j in range(i + 1, len(prices)):
profit = prices[j] - prices[i]
max_profit = max(max_profit, profit)
return max_profit
Полная реализация с тестами
def max_profit(prices):
if not prices or len(prices) < 2:
return 0
min_price = prices[0]
max_profit_val = 0
for price in prices[1:]:
potential_profit = price - min_price
max_profit_val = max(max_profit_val, potential_profit)
min_price = min(min_price, price)
return max_profit_val
test_cases = [
([7, 1, 5, 3, 6, 4], 5),
([7, 6, 4, 3, 1], 0),
([2, 4, 1], 2),
([1], 0),
([], 0),
([5, 5, 5, 5], 0),
([1, 2, 3, 4, 5], 4),
]
for prices, expected in test_cases:
result = max_profit(prices)
status = "OK" if result == expected else "FAIL"
print(f"{status} max_profit({prices}) = {result}")
Вариация: Несколько сделок
def max_profit_multiple(prices):
max_profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i - 1]:
max_profit += prices[i] - prices[i - 1]
return max_profit
print(max_profit_multiple([7, 1, 5, 3, 6, 4])) # 7
Анализ сложности
Оптимальное решение:
- Время: O(n) - один проход
- Память: O(1) - только переменные
Наивное решение:
- Время: O(n^2) - все пары
- Память: O(1)
Почему работает
Максимальная прибыль = max(цена[j] - цена[i]) где i < j
Это равно max(цена[j] - min(цена[0..j-1]))
Поэтому отслеживаем только минимум слева и текущую цену.
Этот алгоритм показывает важность единственного прохода через данные для линейного решения временных рядов.