买卖股票的最佳时机
一、问题描述
LeetCode:122. 买卖股票的最佳时机 II
“买卖股票的最佳时机 II” 问题设定如下:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。与只能进行一次买卖的 “买卖股票的最佳时机” 不同,在本题中,我们可以尽可能地完成更多的交易(多次买卖一支股票),但必须遵循一个规则:在再次购买前必须出售掉之前的股票 ,即不能同时参与多笔交易,目标是计算出能够获得的最大利润。
例如,给定价格数组 [7, 1, 5, 3, 6, 4],通过合适的买卖策略,我们可以实现最大利润。第一天价格为 7,第二天价格降到 1,此时买入,第三天价格升至 5 时卖出,获利 4;接着在第四天价格为 3 时再次买入,第五天价格涨到 6 时卖出,又获利 3。最终总利润为 7。
二、思路1
当看读完题目后,第一个想法就是低买高卖,于是沿着这个思路我想到的是寻找股票波动的波峰与波谷,在波谷的时候买在波峰的时候买。这种方法需要考虑边界问题,判断波峰与波谷来决定是否买入或者卖出,同时还要记录是否持有股票。 代码如下:
var maxProfit = function(prices) {
// 低买高卖:在波谷买入,波峰卖出(原始思路修复版)
if (prices.length < 2) return 0;
let profit = 0;
let hasStock = false; // 跟踪是否持有股票
let buyPrice = 0;
for (let i = 0; i < prices.length; i++) {
// 最后一天如果持有股票则卖出
if (i === prices.length - 1) {
if (hasStock) {
profit += prices[i] - buyPrice;
hasStock = false;
}
break;
}
// 波谷:当前价格低于后一天,且未持有股票时买入
if (!hasStock && prices[i] < prices[i + 1]) {
buyPrice = prices[i];
hasStock = true;
}
// 波峰:当前价格高于后一天,且持有股票时卖出
else if (hasStock && prices[i] > prices[i + 1]) {
profit += prices[i] - buyPrice;
hasStock = false;
}
}
return profit;
};
三、思路2
更简单的做法是是贪心算法。贪心算法的本质是在每一步选择中都采取当前状态下的最优解,从而希望最终得到全局最优解。在股票买卖问题中,有一个关键规律:只要第二天的股价高于当天股价,就在当天买入,第二天卖出,这样就能保证每一次盈利都被纳入总利润中。
具体来说,我们遍历整个价格数组,从第二天开始,比较当天价格与前一天价格。如果当天价格大于前一天价格,说明存在盈利空间,将这个差值(即当天与前一天的价格差)累加到总利润中。通过这种方式,我们可以在满足交易规则的前提下,实现利润最大化。 代码如下:
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
// 上涨就卖 下降不买
let result = 0;
for (let i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) result += prices[i] - prices[i - 1];
}
return result
};
在上述代码中,首先初始化利润 result 为 0。然后通过 for 循环遍历价格数组,索引从 1 开始(因为要与前一天价格比较)。当发现当天价格高于前一天价格时,将价格差累加到 result 中。最后返回计算得到的最大利润。