轻轻松松搞懂股票问题

122-买卖股票的最佳时机 II

题目

买卖无数次

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

思路

  • 以某个价格为基准,遍历天数,会遇到两种可能,由于我们只能买卖无数次,因此对于这两种操作如下:
    • 比当前大,那么就计算收益,同时更新最小值及下次收益;
    • 比当前小,那么买最小的呀;

解法一

func maxProfit(prices []int) int {
    if len(prices) == 0 {
        return 0
    }
    
    res, min := 0, prices[0]
    
    for i := 1; i < len(prices); i++ {
        if prices[i] < min {
            min = prices[i]
        } else {
            res += prices[i] - min
            min = prices[i]
        }
    }
    
    return res
}

解法二

func maxProfit(prices []int) int {
    buy, sell := math.MaxInt32, math.MinInt32
    res := 0    // 总收益

    for i := 0; i < len(prices); i++ {
        buy = min(buy, prices[i])               //  可以理解为两次交易之间的股票最小值
        sell = max(sell, prices[i] - buy)       // 一次交易的收益

        // sell > 0 表示完成一次买卖,所以更新buy;
        if sell > 0 {
            res += sell 
            buy = prices[i]
            sell = 0
        }
    }

    return res
}

func max(a, b int) int {
    if a < b {
        return b
    } 
    return a
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

解法三

  • 初始值:第1天,不持有股票,收益为0;持有股票,收益为-prices[0];
  • 状态变量:天数,是否持有股票;
  • 备忘录矩阵:dp[i][j],i表示天数,j表示是否持有股票,0表示不持有,1表示持有;
  • 决策:
    • i天持有股票 = max(第i-1天无交易, 第i-1天买入股票)
    • i天不持有股票 = max(第i-1天无交易,第i-1天卖出股票)
func maxProfit(prices []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])
        dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
    }

    return dp[len(prices) - 1][0]
}

func max(a, b int) int {
    if a < b {
        return b
    } 
    return a
}

B站视频

兄弟们,一起来刷题啊!!! 股票问题B站视频链接

总结

dp[i][0][k] = max(dp[i-1][0][k] (无交易) + dp[i][1][k-1] + prices[i] (卖出))

dp[i][1][k] = max(dp[i-1][1][k] (无交易) + dp[i][0][k] - prices[i] (买入))

只要明白这个状态转移方程,这类问题就非常丝滑啦;

股票问题汇总

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值