开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情
背景
今天笔者刷了 2 道力扣题 -- 买卖股票的最佳时机 和 买卖股票的最佳时机 II,思有所得,分享给掘友们。
股票题目
股票问题讨论的是:
给定一个数组 prices 代表一支股票的价格波动,它的第 i 个元素 prices[i] 代表这支股票在第 i+1 天的价格。
一次交易是:你选择在某一天买入,并在未来的某一天(数组给出的范围内)卖出。
股票问题1
问题1的条件是只能进行一次交易,返回能获取的最大利润,如果不能获取任何利润,返回 0,对应力扣题 买卖股票的最佳时机。
思路
笔者的整体思路是,计算所有i位置卖出的最大利润,从中找出最大的那个。
如何得到 i位置卖出的最大利润?
只需要用 prices[i] 减去 i位置之前的最小价格,笔者用 min 代表这个最小价格,那么有 2 种情况:
prices[i] - min是负数或零,说明i位置之前的价格都不低于i位置价格,则i位置卖出的最大利润为0。prices[i] - min是正数,则i位置卖出的最大利润为prices[i] - min。
遍历数组计算每个 i 位置的最大利润,这个过程是从左到右的,所以:
- 可以同时维护
i 之前的最小价格。 - 可以实时计算出目前
已计算位置最大利润中,最大的那个。
算法流程非常顺畅,下面展示用 typescript 的实现:
function maxProfit(prices: number[]): number {
let min = prices[0];
let max = 0;
for (let i = 1, len = prices.length; i < len; i++) {
max = Math.max(Math.max(prices[i] - min, 0), max);
min = Math.min(prices[i], min);
}
return max;
}
股票问题2
问题2的条件是能进行无限次交易,对应力扣题 买卖股票的最佳时机 II。
思路
笔者的思路是将所有的爬坡累加起来。爬坡指的是股票价格波动中所有的上升涨幅。比如 [7,1,5,3,6,4] 中, 上升涨幅 有两段,一段是 [1,5] 涨幅 4,另一段是 [3,6] 涨幅 3。
而计算所有的爬坡这一步,为了更好地 coding,每一个爬坡可以分解成一个一个的小涨幅累加来实现。
比如 [1,3,7,1,4,6],这里的爬坡是 [1,3,7] 和 [1,4,6]。对于 [1,3,7] 我们不要计算 7-1=6 来得到上升幅度,那样要找波谷很费时间,可以通过 prices[i] - prices[i-1] 这样一个一个的小涨幅累加的形式算出整条爬坡,比如 7-1=6 可以分成 3-1=2 加 7-3=4 来做:
如果遇到 prices[i]-prices[i-1] <= 0 的情况,如上图中的 [7,1],就说明 i 位置股价下跌了,是没有 爬坡 的,利润是 0。
整个流程非常平滑,用 typescript 实现如下:
function maxProfit(prices: number[]): number {
let max = 0;
for (let i = 1, len = prices.length; i < len; i++) {
max += Math.max(prices[i] - prices[i-1], 0);
}
return max;
}
感谢
笔者学习 左程云老师 的算法课程多年,从而搭建了算法的知识体系,并且学习到非常多的实用技巧,本文思路很大一部分来源于左老师的课程,在此致谢 🙏。
总结
本文从两道力扣题入手,介绍了解决股票问题的思路,笔者认为首要是整体思路,然后分而治之,最后优化代码细节,这样才能写出优雅解决问题的代码。
「保持学习 主动思考 坚持输出」,我是前端涤生,欢迎掘友们加我微信ronnychan0820交流🍺,希望这篇文章可以帮到您~ 🎉