代码随想录算法训练营第四十一天 |动态规划part08

65 阅读3分钟

代码随想录算法训练营第四十一天 |动态规划part08

121 买卖股票的最佳时机I

image-20250120001000690.png

思路:两次for循环,dp[i] [j]表示第i天买入第j天卖出所得的利润,代码如下:

prices = [2,1,2,1,0,1,2]
dp = [[0 for i in range(len(prices)+1)] for j in range(len(prices)+1)]
# print(dp)
for i in range(1, len(prices)):
    for j in range(i+1, len(prices)+1):
        dp[i][j] = prices[j-1] - prices[i-1]
max_ = 0
for i in range(1, len(prices)):
    for j in range(i+1, len(prices)+1):
        if dp[i][j] > max_:
            max_ = dp[i][j]
print(max_)

以上代码是过不去的,因为时间复杂度太高了。

  • 确定dp数组以及下标的含义

    • dp[i] [0] 持有这支股票的最大金额
    • dp[i] [1] 不持有这支股票的最大金额
  • 递推公式

    • dp[i] [0] = max(dp[i-1] [0] , -price[i]) (第i-1天也有这支股票;第i天买入这支股票)
    • dp[i] [1] = max(dp[i-1] [1] , dp[i-1] [0]+price[i]) ((第i-1天也没有这支股票;第i天卖出这支股票,也就是第i-1天有这支股票))
  • dp数组如何初始化

    • dp[0] [0] = -price[0]
    • dp[0] [1] = 0
  • 遍历顺序

    • 从前往后打印
  • 打印dp数组

    • return dp[i-1] [-1]
dp = [[0,0] for i in range(len(prices))]
dp[0][0] = prices[0] * (-1)
dp[0][1] = 0
for i in range(1,len(prices)):
    dp[i][0] = max(dp[i-1][0],-prices[i])
    dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
return dp[-1][1]

122 买卖股票的最佳时机II

image-20250120001010370.png

思路:和上一题几乎一模一样,不过这一次股票可以买卖多次了,所以

有股票时的最大金额 = max(前一天也有;前一天没有股票,今天买了股票了)

dp[i] [0] = max(dp[i-1] [0] , dp[i-1] [1] - prices[i])

dp = [[0,0] for i in range(len(prices))]
dp[0][0] = -prices[0]
dp[0][1] = 0
for i in range(1,len(prices)):
    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[-1][1]

也可以采用贪心的思路:

result = []
for i in range(1,len(prices)):
    result.append(prices[i] - prices[i-1])
sum_ = 0
for i in result:
    if i > 0 :
        sum_ += i
return sum_

123 买卖股票的最佳时机III

image-20250120001022486.png

这道题一下子就难度上来了,关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。

  • 确定dp数组以及下标的含义

    • dp[i] [0] 不操作
    • dp[i] [1] 第一次持有
    • dp[i] [2] 第一次不持有
    • dp[i] [3] 第二次持有
    • dp[i] [4] 第二次不持有
  • 递推公式

    • dp[i] [0] = dp[i-1] [0] (可以不操作)
    • dp[i] [1] = max(dp[i-1] [1] ,dp[i-1] [0] - prices[i])
    • dp[i] [2] = max(dp[i-1] [2] ,dp[i-1] [1] + prices[i])
    • dp[i] [3] = max(dp[i-1] [3] ,dp[i-1] [2] - prices[i])
    • dp[i] [4] = max(dp[i-1] [4] ,dp[i-1] [3] + prices[i])
  • dp数组如何初始化

    • dp[i] [0] = 0
    • dp[i] [1] = -prices[0]
    • dp[i] [2] = 0
    • dp[i] [3] = -prices[0]
    • dp[i] [4] = 0
  • 遍历顺序

    • for i in range(1, len(prices)):
  • 打印dp数组

    • return dp[-1] [4]
# prices = [7, 6, 4, 3, 1]
dp = [[0] * 5 for i 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] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
    dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i])
    dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i])
    dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i])
# print(dp)
return dp[-1][4]