买卖股票的最佳时机
各位未来的华尔街之狼,今天我们来玩转LeetCode的股票买卖游戏!无论你是只想当一次"一锤子买卖"的佛系股民,还是想要高频交易的华尔街之狼,这篇攻略都能让你赚得盆满钵满!(虚拟货币版)
该题目来自于力扣《买卖股票的最佳时机》系列题目,121,122 题目
🔍 题目描述
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。如果你不能获取任何利润,返回 0 。
只能交易一次(某一天买进、某一天卖出),最大利润是多少?
可以交易多次(每一天都可以决定是否购买和/或出售股票),最大利润又是多少?
一、只能交易一次(121)
💡 解题思路拆解
我们需要找出给定数组中两个数字之间的最大差值,而且第二个数字(卖出价格)必须大于第一个数字(买入价格)。
1. 暴力解法
🎯 代码实现(Go)
func maxProfit(prices []int) int {
maxNumber := 0
for i := 0; i < len(prices); i++ {
for j := i; j < len(prices); j++ {
profit := prices[j] - prices[i]
if profit > 0 && profit > maxNumber {
maxNumber = profit
}
}
}
return maxNumber
}
⚠️ 警报:当股票数据超过1000天时,这段代码会让你体验到什么叫"等到天荒地老"!什么叫红色告警。!
2、动态规划
如果我们将给定的数组以每天股价折形图(文章开头)的形式展示出来,那想获得最大利润,是不是就在最低点买进,最高点卖出呢?
因此,我们只需要遍历一遍数组,记录最低点(最小数字),然后每天都看看利润是否最大即可。废话不多说,直接上代码。
🎯 代码实现(Go)
func maxProfit(prices []int) int {
minPrice := prices[0]
profit := 0
for i := 1; i < len(prices); i++ {
if prices[i] < minPrice {
minPrice = prices[i]
} else {
tmpProfit := prices[i] - minPrice
if tmpProfit > profit {
profit = tmpProfit
}
}
}
return profit
}
这样时间复杂度为O(n)。
股票操作,只能买卖一次,那怎么行呢,那怎么体现兄弟们的实力呢,对吧。所以说不限制交易次数 最大利润又是多少呢?
二、不限制交易次数(122)
1、动态规划
如果不限制次数,只需要在每个谷底(区间段内最低点)买进,谷峰(谷底过后的第一个峰值)卖出,获得所有利润。**抓住每一个上涨波段!**我们继续延用之前说的动态规划。
🎯 代码实现(Go)
func maxProfit2(prices []int) int {
day := len(prices)
if day < 2 {
return 0
}
totalProfit := 0
nowProfit := 0
nowStatus := 0 // 1 持有,0 未持有
nowBuyPrice := 0
if prices[0] < prices[1] {
nowStatus = 1
nowBuyPrice = prices[0]
}
for i := 1; i < day; i++ {
if i == day-1 {
// 最后一天
if nowStatus == 1 && prices[i] > prices[i-1] {
totalProfit += prices[i] - nowBuyPrice
}
break
}
if nowStatus == 1 {
nowProfit = prices[i] - nowBuyPrice
}
// 是否需要买进卖出
if prices[i+1] > prices[i] {
if nowStatus == 0 {
nowStatus = 1
nowBuyPrice = prices[i]
}
} else {
totalProfit += nowProfit
nowProfit = 0
nowStatus = 0
nowBuyPrice = 0
}
}
return totalProfit
}
但是这样看起来就感觉很复杂,既然是最大利润,那是不是只要今天比前一天赚了,都加起来是不是就可以了呢,对,没错。我们就可以用到贪心算法,直接上代码。
🎯 代码实现(Go)
func maxProfit2(prices []int) int {
day := len(prices)
if day < 2 {
return 0
}
totalProfit := 0
for i := 1; i < day; i++ {
if prices[i] > prices[i-1] {
totalProfit += prices[i] - prices[i-1]
}
}
return totalProfit
}
💎 核心思想:把整个K线图拆解成无数个"↗"小波段,每个小坡都赚它一个鸡腿🍗!
🤔 高阶挑战:如果只能交易两次?
互动话题:
- 当遇到123. 买卖股票的最佳时机 III时,你会如何设计算法?
- 是选择"先赚个大的再赚个小的",还是"细水长流分两次"?
- 💡 提示:可以尝试用动态规划记录四个状态!
👉 在评论区留下你的解题思路吧!
🚀 坚持每日一题,小白也能稳步上升!