动态规划part11 | ● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV


123.买卖股票的最佳时机III

123.买卖股票的最佳时机III

思路

确定dp数组以及下标的含义
一天一共就有五个状态,

没有操作 (其实我们也可以不设置这个状态)
第一次持有股票
第一次不持有股票
第二次持有股票
第二次不持有股票
dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。

需要注意:dp[i][1],表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是很多同学容易陷入的误区。

例如 dp[i][1] ,并不是说 第i天一定买入股票,有可能 第 i-1天 就买入了,那么 dp[i][1] 延续买入股票的这个状态。

思路代码

func maxProfit(prices []int) int {
    dp:=make([][]int,2)
    for i:=0;i<2;i++{
        dp[i]=make([]int,4)
    }
    dp[0][0]=-prices[0]
    dp[0][2]=-prices[0]
    for i:=1;i<len(prices);i++{
        dp[i%2][0]=max(dp[(i+1)%2][0],-prices[i])
        dp[i%2][1]=max(dp[(i+1)%2][1],dp[(i+1)%2][0]+prices[i])
        dp[i%2][2]=max(dp[(i+1)%2][2],dp[(i+1)%2][1]-prices[i])
        dp[i%2][3]=max(dp[(i+1)%2][3],dp[(i+1)%2][2]+prices[i])
    }
    index:=(len(prices)-1)%2
    return dp[index][3]
}

func max(i,j int)int{
    if i<j{
        return j
    }
    return i
}

困难

如果能够买两次的话,那么就有五个状态了,所以每一层的dp长度为5.第一个状态可以舍去,所以每层dp长度为4。


188.买卖股票的最佳时机IV

188.买卖股票的最佳时机IV

思路

和上题一样,只不过状态更多罢了

思路代码

func maxProfit(k int, prices []int) int {
   dp:=make([][]int,len(prices)) 
   for i,_:=range dp{
       dp[i]=make([]int,k*2)
   }
   for i:=0;i<k;i++{
       dp[0][i*2]=-prices[0]
   }
   for i:=1;i<len(prices);i++{
       for j:=0;j<k;j++{
           if j==0{
               dp[i][0]=max(dp[i-1][0],-prices[i])
           }else{
               dp[i][j*2]=max(dp[i-1][j*2],dp[i-1][j*2-1]-prices[i])
           }
           dp[i][j*2+1]=max(dp[i-1][j*2+1],dp[i-1][j*2]+prices[i])
       }
   }
   return dp[len(prices)-1][k*2-1]
}

func max(i,j int)int{
    if i<j{
        return j
    }
    return i
}

官方代码

func maxProfit(k int, prices []int) int {
    if k == 0 || len(prices) == 0 {
        return 0
    }
    
    dp := make([][]int, len(prices))
    status := make([]int, (2 * k + 1) * len(prices))
    for i := range dp {
        dp[i] = status[:2 * k + 1]
        status = status[2 * k + 1:]
    }
    for j := 1; j < 2 * k; j += 2 {
        dp[0][j] = -prices[0]
    }
    
    for i := 1; i < len(prices); i++ {
        for j := 0; j < 2 * k; j += 2 {
            dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i])
            dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i])
        }
    }
    return dp[len(prices) - 1][2 * k]
}

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

困难

状态数为2*k个


今日收获

股票问题允许交易k次,此时可以设多个状态(2k个),代表第几次交易的持有股票和不持有股票。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值