最近做了LeetCode买卖股票相关的题目,把解题思路都记录下来,方便以后回顾。
相关链接:
121. 买卖股票的最佳时机
122. 买卖股票的最佳时机 II
123. 买卖股票的最佳时机 III
188. 买卖股票的最佳时机 IV
309. 最佳买卖股票时机含冷冻期
714. 买卖股票的最佳时机含手续费
121.买卖股票的最佳时机:
1.dp数组以及下标的含义:
dp[i][0]表示第i天没有股票时所拥有的最多现金,dp[i][1]表示第i天有股票时所拥有的最多现金。
2.递推公式:
如果第i天没有股票,可以由以下两种情况推出:
(1).第i-1天没有股票
(2).第i-1天有股票,第i天把股票卖了
对应的递推公式为dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i])
如果第i天有股票,可以由以下两种情况推出:
(1).第i-1天有股票
(2).第i-1天没有股票,第i天买股票
对应的递推公式为dp[i][1]=max(dp[i-1][1],-prices[i])
这里要注意的是第i天没有股票的情况(2),因为题目要求只能买一次股票,所以这时候第i-1天所拥有的现金为0。
3.初始化:
dp[0][0]=0,dp[0][1]=-prices[0],
给出对应的代码:
func maxProfit(prices []int) int {
dp := make([][2]int, len(prices))
dp[0][0] = 0
dp[0][1] = -prices[0]
// 0:无股票
// 1:持有股票
for i := 1; i < len(dp); i++ {
dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
dp[i][1] = max(dp[i-1][1], -prices[i])
}
return dp[len(dp)-1][0]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
122.买卖股票的最佳时机II:
1.dp数组以及下标的含义:
dp[i][0]表示第i天没有股票时所拥有的最多现金,dp[i][1]表示第i天有股票时所拥有的最多现金。
2.递推公式:
如果第i天没有股票,可以由以下两种情况推出:
(1).第i-1天没有股票
(2).第i-1天有股票,第i天把股票卖了
对应的递推公式为dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i])
如果第i天有股票,可以由以下两种情况推出:
(1).第i-1天有股票
(2).第i-1天没有股票,第i天买股票
对应的递推公式为dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
这里要注意的是第i天没有股票的情况(2),因为可以买卖多次股票,所以这时候第i-1天所拥有的现金为dp[i-1][0]。
3.初始化:
dp[0][0]=0,dp[0][1]=-prices[0],
给出对应的代码:
func maxProfit(prices []int) int {
dp := make([][]int, len(prices))
for i := 0; i < len(dp); i++ {
dp[i] = make([]int, 2)
}
// 0:持有现金
// 1:持有股票
dp[0][0] = 0
dp[0][1] = -prices[0]
for i := 1; i < len(dp); i++ {
dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i])
}
return dp[len(dp)-1][0]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
123.买卖股票的最佳时机III:
1.dp数组以及下标的含义:
dp[i][k][0]表示第i天最多进行k次交易,并且最终没有股票时所拥有的最多现金,dp[i][k][1]表示第i天最多进行k次交易,并且最终有股票时所拥有的最多现金。
2.递推公式:
如果第i天没有股票,可以由以下两种情况推出:
(1).第i-1天没有股票
(2).第i-1天有股票,第i天把股票卖了
对应的递推公式为dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i])
如果第i天有股票,可以由以下两种情况推出:
(1).第i-1天有股票
(2).第i-1天没有股票,第i天买股票
把买股票看做一次交易,则对应的递推公式为dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i])
这里要注意的是第i天没有股票的情况(2),因为我把买股票看做一次交易,所以这时候第i-1天所拥有的现金为dp[i-1][k-1][0]。
3.初始化:
dp[0][k][0]=0,dp[0][k][1]=-prices[0],
给出对应的代码:
func maxProfit(prices []int) int {
dp := make([][3][2]int, len(prices))
dp[0][1][0] = 0
dp[0][1][1] = -prices[0]
dp[0][2][0] = 0
dp[0][2][1] = -prices[0]
// 0:无股票
// 1:持有股票
for i := 1; i < len(dp); i++ {
dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][1][1]+prices[i])
dp[i][1][1] = max(dp[i-1][1][1], dp[i-1][0][0]-prices[i])
dp[i][2][0] = max(dp[i-1][2][0], dp[i-1][2][1]+prices[i])
dp[i][2][1] = max(dp[i-1][2][1], dp[i-1][1][0]-prices[i])
}
return dp[len(dp)-1][2][0]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
188.买卖股票的最佳时机IV:
与123.买卖股票的最佳时机III类似,直接给出代码:
func maxProfit(k int, prices []int) int {
if len(prices) == 0 {
return 0
}
dp := make([][][]int, len(prices))
for i := 0; i < len(dp); i++ {
dp[i] = make([][]int, k+1)
for j := 0; j < k+1; j++ {
dp[i][j] = make([]int, 2)
}
}
for i := 1; i <= k; i++ {
dp[0][i][0] = 0
dp[0][i][1] = -prices[0]
}
for i := 1; i < len(prices); i++ {
for j := 1; j < k+1; j++ {
dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1]+prices[i])
dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i])
}
}
return dp[len(dp)-1][k][0]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
其实这几题都是类似的,不同的地方在于最大交易次数。
309.最佳买卖股票时机含冷冻期:
与122.买卖股票的最佳时机II类似,可以多次交易,不同的地方在于如果想要在第i天买入股票,因为有冷冻期,所以第i-1天不能卖出股票,对应的递推公式为dp[i][1]=max(dp[i-1][1],dp[i-2][0]-prices[i]),
对应的代码:
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
dp := make([][2]int, len(prices))
dp[0][0] = 0
dp[0][1] = -prices[0]
for i := 1; i < len(dp); i++ {
dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
dp[i][1] = max(dp[i-1][1], dp[max(0, i-2)][0]-prices[i])
}
return dp[len(dp)-1][0]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
714.买卖股票的最佳时机含手续费:
与122.买卖股票的最佳时机II类似,可以多次交易,不同的地方在于如果想要在第i天卖出股票,需要付手续费,对应的递推公式为dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee),
对应的代码:
func maxProfit(prices []int, fee int) int {
dp := make([][2]int, len(prices))
dp[0][0] = 0
dp[0][1] = -prices[0]
for i := 1; i < len(prices); i++ {
dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i]-fee)
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i])
}
return dp[len(dp)-1][0]
}
func max(x, y int) int {
if x > y {
return x
}
return y
}