📚 小白学算法 | 每日一题 | 股市大作战!📈

87 阅读3分钟

买卖股票的最佳时机

image.png

各位未来的华尔街之狼,今天我们来玩转LeetCode的股票买卖游戏!无论你是只想当一次"一锤子买卖"的佛系股民,还是想要高频交易的华尔街之狼,这篇攻略都能让你赚得盆满钵满!(虚拟货币版)

该题目来自于力扣《买卖股票的最佳时机》系列题目,121122 题目

🔍 题目描述

给定一个数组 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时,你会如何设计算法?
  • 是选择"先赚个大的再赚个小的",还是"细水长流分两次"?
  • 💡 提示:可以尝试用动态规划记录四个状态!

👉 在评论区留下你的解题思路吧!

🚀 坚持每日一题,小白也能稳步上升!