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个),代表第几次交易的持有股票和不持有股票。