股票交易时机选择是每个投资者都会面临的经典问题。这道题目看似简单,实则包含了动态规划、贪心算法等多种解题思路的巧妙应用。我曾在量化交易系统中多次实现类似算法,发现即使是经验丰富的开发者,也容易在边界条件处理上栽跟头。
问题的本质是:给定一个数组表示某股票第i天的价格,设计算法计算你能获得的最大利润。你最多只能完成一笔交易(即买入和卖出一支股票一次),且必须在再次购买前出售掉之前的股票。
最直观的解法是使用双重循环遍历所有可能的买卖组合:
python复制def maxProfit(prices):
max_profit = 0
for i in range(len(prices)):
for j in range(i+1, len(prices)):
profit = prices[j] - prices[i]
if profit > max_profit:
max_profit = profit
return max_profit
注意:这种方法在LeetCode上会因超时无法通过,但其清晰的逻辑值得初学者理解
该算法的时间复杂度为O(n²),空间复杂度O(1)。当n较大时(如n=10⁵),计算次数将达到10¹⁰量级,明显不符合实际需求。
通过观察可以发现,我们只需要记录历史最低点,然后在每一天考虑:如果今天卖出,能获得多少利润?
python复制def maxProfit(prices):
min_price = float('inf')
max_profit = 0
for price in prices:
if price < min_price:
min_price = price
elif price - min_price > max_profit:
max_profit = price - min_price
return max_profit
该算法维护两个关键变量:
由于买卖必须在不同天进行,且卖出在买入之后,因此只需要保证计算利润时使用的买入价是之前的最低点即可。
实际应用中需要考虑以下边界条件:
改进后的健壮性实现:
python复制def maxProfit(prices):
if len(prices) < 2:
return 0
min_price = prices[0]
max_profit = 0
for price in prices[1:]:
max_profit = max(max_profit, price - min_price)
min_price = min(min_price, price)
return max_profit
完整的测试应当包含:
python复制test_cases = [
([7,1,5,3,6,4], 5), # 常规情况
([7,6,4,3,1], 0), # 持续下跌
([], 0), # 空输入
([5], 0), # 单元素
([2,4,1], 2), # 最低点不在开头
([3,2,6,5,0,3], 4) # 含0值情况
]
如果允许进行多次交易(但必须在再次购买前出售),问题变为122题。其解法更简单:
python复制def maxProfit(prices):
profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
profit += prices[i] - prices[i-1]
return profit
当加入卖出后需要冷冻一天的限制(309题),需要使用状态机思路:
python复制def maxProfit(prices):
if not prices:
return 0
n = len(prices)
hold = [0] * n
unhold = [0] * n
hold[0] = -prices[0]
for i in range(1, n):
if i == 1:
hold[i] = max(hold[i-1], -prices[i])
else:
hold[i] = max(hold[i-1], unhold[i-2] - prices[i])
unhold[i] = max(unhold[i-1], hold[i-1] + prices[i])
return unhold[-1]
我曾在一个量化项目中因忽略手续费导致策略回测结果虚高30%,这个教训说明理论算法必须结合实际交易约束。