Day41 - 动态规划 Part08

54 阅读2分钟

基础

股票问题

刷题

  1. 买卖股票的最佳时机

leetcode.cn/problems/be…

image.png

动态规划:

image.png

动规五部曲:

  1. 确定dp数组含义:

    dp[i][0] 是持有股票的最大金额,包括买入及买入之后的情况

    dp[i][1] 是不持有股票的最大金额,包括卖出和卖出之后的情况

  2. 确定dp数组递推公式

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

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

  3. 确定dp数组初始化

    dp[0][0] = -prices[0]

    dp[0][1] = 0

  4. 确定dp数组遍历顺序

    从前向后

  5. 打印dp数组

大佬版本:

image.png

  1. 买卖股票的最佳时机II

leetcode.cn/problems/be…

image.png

递归五部曲:

  1. 确定dp数组含义
dp := [2][2]int{}

dp[i][0] 是当天持有股票的最大金额

max(dp[i-1][0],今天购入的最大金额)

dp[i][1] 是当天不持有股票的最大金额

max(dp[i-1][1],今天卖出股票的最大金额)

2. 确定dp数组递推公式

如上

  1. 确定dp数组初始化
dp[i][0] = 0-prices[0]   // 第一天买入股票
dp[i][1] = 0             // 第一天不持有股票就是没操作,为0

4. 确定dp数组遍历顺序

从左向右,优化dp数组,因为dp公式中只需要前一天的数据,故遍历只需要遍历i%2 和 (i-1)%2

  1. 打印dp数组

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

leetcode.cn/problems/be…

image.png

动规五部曲:

  1. 确定dp数组含义
  2. 确定dp数组递推公式
// 我的做法是定义两个dp数组,一个是第一次买卖的,一个是第二次买卖的
// 这里主要讲解一个dp数组的情况

// 第一层是切片,第二层是数组,因为切片和数组的定义方法不太一样
dp := make([][4]int, len(prices))

// dp[i][0] 第一次持有股票的最大金额,因为是第一次持有,前面没有发生交易,是0-prices[i]
dp[i][0] = max(dp[i-1][0], 0-prices[i])

// dp[i][1] 第一次不持有股票的最大金额
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])

// dp[i][2] 第二次持有股票的最大金额
dp[i][2] = max(dp[i-1][2], dp[i-1][1] - prices[i])

// dp[i][3] 第二次不持有股票的最大金额
dp[i][3] = max(dp[i-1][3], dp[i-1][2] + prices[i])

  1. 确定dp数组初始化
dp[0][0] = -prices[0]
dp[0][1] = 0
//因为在实现第二次买入的时候,需要2天时间买卖,所以不可能在第一天和第二天发生第二次买入
// 因为可以不发生第二次买卖,比如len(prices) <= 3
// 其实这种情况可以理解为不发生第一次,直接发生第二次 --- 总数也是1次
dp[0][2] = -prices[0]
dp[0][3] = 0

  1. 确定dp数组遍历顺序

从左向右

  1. 打印dp数组

总结