leetcode(力扣) 123. 买卖股票的最佳时机 III (动态规划)

文章目录

  • 题目描述
  • 思路分析
  • 完整代码

题目描述

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:
输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

示例 2:
输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。

示例 4:
输入:prices = [1]
输出:0

思路分析

这道题的前置两个题

  • 121.买卖股票的最佳时机
  • 122.买卖股票的最佳时机 Ⅱ

这道题在上一道题的基础上再次升级,上一道题是可以无限买卖,这道题是规定了只允许买两次卖两次。你也可以为了追求最大利润选择不操作或者只买卖一次。

来规矩 动态规划五步走:

1.确定dp数组含义:

和之前的思路一样,定义出来i天所有的可能状态。

dp[i][0] : 表示 第 i 天无操作,保持之前的状态 时手里的最大金额。
dp[i][1]: 表示 第 i 天 第一次持有股票的状态 时手里的最大金额。
dp[i][2]: 表示 第 i 天 第一次不持有股票的状态 时手里的最大金额。
dp[i][3]: 表示 第 i 天 第二次持有股票的状态 时手里的最大金额。
dp[i][4]: 表示 第 i 天 第二次不持有股票的状态 时手里的最大金额。

稍微说明一下,持有状态,有可能是 i 天当天买入了股票变成了持有状态,或者前几天就买入了,到今天还没卖出,那么今天也是持有状态,不持有状态同理。

2.状态转移公式:

这块没什么难的,和之前的思路是一样的,只不过多了几个状态。


dp[i][1]第i天持有股票 手里的最大金额:
要么是前几天买入的,今天还没卖,所以是持有状态,继承前一天的持有状态就行了。要么是今天刚买入的,则就是前一天无操作时的状态再花掉今天要买股票的钱。
所以就是:dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i])


dp[i][2] 第i天不持有股票 手里最大的金额:
要么是前几天就已经卖掉了,现在还是不持有状态,则继承前一天不持有状态。要么是今天刚卖掉,所以是前一天持有状态,再加上今天要卖掉的钱。
所以就是: dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i])


dp[i][3] 第i天第二次持有股票 手里最大的金额:
同理,前几天已经买入,则继承前两天的第二次持有状态,或者是今天刚买入的,则是前一天不持有状态 再花掉今天买入股票的钱。
所以:dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i])


dp[i][4] 第i天第二次不持有股票 手里最大的金额:
同理。
公式:dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i])

3.初始化dp数组:

一开始dp[0][0]肯定是0没得说。

第一次买入肯定是负钱 dp[0][1] = -prices[0]

第一次卖出选择最差情况,就是无收入情况 dp[0][2] = 0

第二次买入,看递推公式可以知道,和第一次卖出有关,所以这里设置为-prices[0]

第二次卖出,同理了 是0。

4.遍历顺序:
这个没得说,正向遍历。

5.模拟举例dp数组的值:

偷懒的一步,debug用~出错了回来做着一步。

完整代码

class Solution:
    def maxProfit(self, prices: List[int]) -> int:

        dp = [[0 for i in range(5)] for j in range(len(prices))]

        dp[0][0] = 0
        dp[0][1] = -prices[0]
        dp[0][2] = 0
        dp[0][3] = -prices[0]
        dp[0][4] = 0

        for i in range(1,len(prices)):
        	# 无操作
            dp[i][0] = dp[i-1][0]
            # dp[i][1]第i天持有股票 手里的最大金额
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i])
            # dp[i][2] 第i天不持有股票 手里最大的金额
            dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i])
            # dp[i][3] 第i天第二次持有股票 手里最大的金额
            dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i])
            # dp[i][4] 第i天第二次不持有股票 手里最大的金额
            dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i])
        print(dp[-1][4])
        return dp[-1][4]

你可能感兴趣的:(交流学习,个人笔记,leetcode,python)