代码随想录动态规划part08|121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III
-
- 121.买卖股票的最佳时机
- 122.买卖股票的最佳时机II
- [123.买卖股票的最佳时机III -- 困难](#123.买卖股票的最佳时机III -- 困难)
121.买卖股票的最佳时机
思路
:
本题这一只股票只买卖一次
暴力解法、动态规划解法
动态规划:
- dp数组的含义:
要用二维dp数组:dp[i][0], dp[i][1]分别表示持有这只股票所得的最大现金和不持有这支股票的最大现金(刚开始手里的钱数为0,那最终的钱数就是利润)。
最终返回max(dp[len(nums-1)][0], dp[len(nums)-1][1]),其实是返回dp[len(nums)-1][1],因为最后一天不持有股票手里的现金才会多 - 递推公式:
a. dp[i][0](第i天已经持有这只股票,可能是之前就持有,也可能是今天才买入持有)
dp[i][0] = max(dp[i-1][0], -price[i]) (这里负数的max就是花费最少,当前手里的现金肯定是负数)
b. dp[i][1](第i天已经不持有这只股票,可能是之前就卖了,也可能是今天才卖掉这只股票)
dp[i][1] = max(dp[i-1][1], dp[i-1][0]+price[i])
c. 思路比较不寻常,注意别想复杂了,准 - dp数组初始化:
dp[0][0] = -price[0]
dp[0][1] = 0 - 遍历顺序:从前往后遍历,不涉及背包中复杂的遍历顺序
python代码
:
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
dp = [[0,0] for _ in range(len(prices)+1)]
# dp = [[0] * 2 for _ in range(length)]
dp[0][0] = -prices[0]
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[len(prices)-1][1]
以前的提交:贪心算法
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
maxprofit = 0
mincost = 90000
for i in range(len(prices)):
if prices[i]<mincost:
mincost = prices[i]
maxprofit = max(maxprofit, prices[i]-mincost)
return maxprofit
122.买卖股票的最佳时机II
思路
:
可用贪心法,本题相比上题改为:可买卖多次
贪心算法:
可买卖多次,第i天买入股票手头上的现金不是0,可能是之前买卖多次获得的利润,所以在递推公式中dp[i][0]需要改变
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])
python代码
:
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
dp = [[0]*2 for _ in range(len(prices))]
dp[0][0] = -prices[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[len(prices)-1][1]
123.买卖股票的最佳时机III -- 困难
思路
:
本题最多可以完成两笔交易,不能同时参与多笔交易
- 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[0][0] = 0
dp[0][1] = -prices[0]
dp[0][2] = 0
dp[0][3] = -prices[0]
dp[0][4] = 0 - 遍历顺序
python代码
:
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
dp = [[0]*5 for _ in range(len(prices))]
dp[0][1], dp[0][3] = -prices[0], -prices[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])
return dp[len(prices)-1][4]
本题可以不用维护一个dp数组,只用4个变量即可(状态压缩)
python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if len(prices) == 0:
return 0
dp = [0] * 5
dp[1] = -prices[0]
dp[3] = -prices[0]
for i in range(1, len(prices)):
dp[1] = max(dp[1], dp[0] - prices[i])
dp[2] = max(dp[2], dp[1] + prices[i])
dp[3] = max(dp[3], dp[2] - prices[i])
dp[4] = max(dp[4], dp[3] + prices[i])
return dp[4]