买卖股票的最佳时机
题目描述
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
text
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。示例 2:
text
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。思路拆解
这道题的核心在于找到一个最低的买入点,以及在这个买入点之后的最高的卖出点。
1. 暴力法(超时)
最简单的想法是两层循环,枚举所有可能的买入和卖出日期,计算利润并取最大值。时间复杂度是 $O(n^2)$,在数据量较大时会超时。
2. 贪心算法(一次遍历)
我们实际上只需要遍历一次数组:
- 假设我们在第
i天卖出,那么为了利润最大,我们应该在第i天之前的最低价格买入。 - 我们维护一个变量
minPrice,表示截止到当前位置的最低股票价格。 - 遍历数组:
- 如果当前价格比
minPrice低,更新minPrice。 - 如果当前价格比
minPrice高,计算当前卖出的利润currentPrice - minPrice,并尝试更新全局最大利润maxProfit。
- 如果当前价格比
这样,我们只需要遍历一次数组即可得到结果。
代码实现
javascript
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
let minPrice = Infinity; // 记录历史最低价
let maxProfit = 0; // 记录最大利润
for (const price of prices) {
if (price < minPrice) {
// 发现更低的价格,更新买入点
minPrice = price;
} else if (price - minPrice > maxProfit) {
// 当前价格卖出能获得更高利润,更新最大利润
maxProfit = price - minPrice;
}
}
return maxProfit;
};运行演示
假设输入 prices = [7, 1, 5, 3, 6, 4]:
price = 7:minPrice更新为 7,maxProfit= 0price = 1:minPrice更新为 1 (比7小),maxProfit= 0price = 5:5 - 1 = 4,maxProfit更新为 4price = 3:3 - 1 = 2, 小于 4, 不更新price = 6:6 - 1 = 5,maxProfit更新为 5price = 4:4 - 1 = 3, 小于 5, 不更新
最终返回 5。
复杂度分析
- 时间复杂度:$O(n)$,只需要遍历一次数组。
- 空间复杂度:$O(1)$,只使用了常数个变量。
