目录
121. 买卖股票的最佳时机
122. 买卖股票的最佳时机 II
123. 买卖股票的最佳时机 III
188. 买卖股票的最佳时机 IV
309. 最佳买卖股票时机含冷冻期
714. 买卖股票的最佳时机含手续费
买卖股票的问题,本质上是一个动态规划的问题。
针对股票买卖这一问题,想获取某一天的最大利润,则在持有股票和卖出股票两种状态中,显然应该是卖出股票状态(即手上没有股票的状态)。
这里持有股票状态为1,卖出股票状态为0的话,则第n-1天,交易k次的利润为:
dp[n][k][0] = max(dp[n-1][k][0],dp[n-1][k][1]+prices[n])
翻译成可以理解的语言为:一个人第n天在交易了k次后没有持有股票,则他可能是:
1.第(n-1)天就没有持有,然后第n天没有产生任何行为;
2.第(n-1)天持有股票,但是第n天卖出了股票。
从中选出最大值即为当前天的最大利润。
第n天持有股票时的最大利润为:
dp[n][k][1] = max(dp[n-1][k][1],dp[n-1][k-1][0]-prices[n])
翻译成可以理解的语言为:一个人第n天在交易了k次后持有股票,则他可能是:
1.第(n-1)天就持有,然后第n天没有产生任何行为;
2.第(n-1)天交易(k-1)次后没有持有股票,但是第n天买入了股票。
以上就是买卖股票的基本状态转移方程。不过为了方程可以迭代成功,我们还需要确定一些初始条件
dp[-1][k][0] = 0
# 因为 i 是从 0 开始的,所以 i = -1 意味着还没有开始,这时候的利润当然是 0 。
dp[-1][k][1] = -infinity
# 还没开始的时候,是不可能持有股票的,用负无穷表示这种不可能。
dp[i][0][0] = 0
# 因为 k 是从 1 开始的,所以 k = 0 意味着根本不允许交易,这时候利润当然是 0 。
dp[i][0][1] = -infinity
# 不允许交易的情况下,是不可能持有股票的,用负无穷表示这种不可能。
将上述结论汇总如下:
#初始条件:
dp[-1][k][0] = dp[n][0][0] = 0
dp[-1][k][1] = dp[n][0][1] = -infinity
#状态转移方程:
dp[n][k][0] = max(dp[n-1][k][0], dp[n-1][k][1] + prices[n])
dp[n][k][1] = max(dp[n-1][k][1], dp[n-1][k-1][0] - prices[n])
这样我们就可以针对买卖股票的问题一一作答
def maxProfit(prices):
#采用股票买卖的标准模板计算
#
import numpy as np
n = len(prices)
#因为只能进行一次买卖,所以不需要考虑k的情况
dp_0,dp_1 = [0]*(n+1),[0]*(n+1)
# 显然一开始没有持有股票的利润为0,而一开始持有股票是不可能的情况
dp_0[-1] = 0
dp_1[-1] = np.float('-inf')
for i in range(n):
dp_0[i] = max(dp_0[i-1],dp_1[i-1] + prices[i])
dp_1[i] = max(dp_1[i-1],-prices[i])
return dp_0[n-1]
相比于第一次只能完成1次交易而言,这一次可以完成多次交易
def maxProfit(prices):
# 运用模板进行计算,常规参数
import numpy as np
n = len(prices)
dp_0 = [0]*(n+1)
dp_1 = [0]*(n+1)
dp_0[-1] = 0
dp_1[-1] = np.float('-inf')
#这里是针对不同问题需要调整的地方
for i in range(n):
temp = dp_0[i-1]
dp_0[i] = max(dp_0[i-1],dp_1[i-1]+prices[i])
dp_1[i] = max(dp_1[i-1],temp-prices[i])
return dp_0[n-1]
下面两道题是在以上基础上进行了一个变换
def maxProfit(prices):
if prices is None or prices is []:return 0
#采用股票买卖的标准模板计算
import numpy as np
n = len(prices)
dp_0,dp_1 = [0]*(n+2),[0]*(n+2)
dp_0[-1] = 0
dp_1[-1] = np.float('-inf')
dp_0[-2] = 0
#逻辑修改的地方
for i in range(n):
dp_0[i] = max(dp_0[i-1],dp_1[i-1] + prices[i])
dp_1[i] = max(dp_1[i-1],dp_0[i-2] - prices[i])
return dp_0[n-1]
def maxProfit(prices, fee):
#常规的计算模板,参数设定
import numpy as np
n = len(prices)
dp_0,dp_1 = [0]*(n+1),[0]*(n+1)
dp_0[-1] = 0
dp_1[-1] = np.float('-inf')
#这里要依据题设进行修改
for i in range(n):
dp_0[i] = max(dp_0[i-1],dp_1[i-1]+prices[i])
dp_1[i] = max(dp_1[i-1],dp_0[i-1] - prices[i] - fee)
return dp_0[n-1]
以下两道题考虑了交易次数的变化,属于困难题
def maxProfit(k, prices):
#采用股票买卖的标准模板计算
import numpy as np
n = len(prices)
deal = [0]*k
dp_0,dp_1 = [deal]*(n+1),[deal]*(n+1)
for i in range(n):
for j in range(1,k+1):
dp_0[-1][j] = 0
dp_1[-1][j] = -prices[i]
dp_0[i][j] = max(dp_0[i-1][j],dp_1[i-1][j] + prices[i])
dp_1[i][j] = max(dp_1[i-1][j],dp_0[i-1][j-1]-prices[i])
return dp_0[n-1][k]